react icon indicating copy to clipboard operation
react copied to clipboard

Bug: useId generated the same ID on server-side for 2 different mounted components when Promise/Suspense is involved

Open Ang-YC opened this issue 1 year ago • 0 comments

React version: 18.3.1

(Also tested on React 19 and seems like it is fixed)

Steps To Reproduce

  1. Create 2 components: Parent and Child, where both components will throw Promise (eg. data fetching)
  2. Call useId on both Parent and Child, and observes they have the same ID generated

Sample code:

const Child = ({ parentId }: { parentId: string }) => {
  const id = useId();
  useAsync(2); // Just assume it is a hook that will throw Promise in first call
  return (
    <ul>
      <li>Parent: {parentId}</li>
      <li>Child: {id}</li>
    </ul>
  );
};

const Parent = () => {
  const id = useId();
  useAsync(1); // Just assume it is a hook that will throw Promise in first call
  return <Child parentId={id} />;
};

Generated HTML:

<ul>
  <li>Parent: <!-- -->:R0:</li>
  <li>Child: <!-- -->:R0:</li>
</ul>

Link to code example: https://codesandbox.io/p/sandbox/react-server-duplicate-useid-nllf55

The current behavior

The ID generated on both mounted components are the same

<ul>
  <li>Parent: <!-- -->:R0:</li>
  <li>Child: <!-- -->:R0:</li>
</ul>

The expected behavior

The ID generated on both mounted components should be different

<ul>
  <li>Parent: <!-- -->:R0:</li>
  <li>Child: <!-- -->:R1:</li>
</ul>

Ang-YC avatar May 08 '24 08:05 Ang-YC