Skip to content

Conversation

sebmarkbage
Copy link
Collaborator

Includes #31412.

The issue is that pushTreeFork stores some global state when reconcile children. This gets popped by popTreeContext in completeWork. Normally completeWork returns its own Fiber again if it wants to do a second pass which will call pushTreeFork again in the next pass. However, SuspenseList doesn't return itself, it returns the next child to work on.

The fix is to keep track of the count and push it again it when we return the next child to attempt.

There are still some outstanding issues with hydration. Like the backwards test still has the wrong behavior in it because it hydrates backwards and so it picks up the DOM nodes in reverse order. tail="hidden" also doesn't work correctly.

There's also another issue with useId and AsyncIterable in SuspenseList when there's an unknown number of children. We don't support those showing one at a time yet though so it's not an issue yet. To fix it we need to add variable total count to the useId algorithm. E.g. by falling back to varint encoding.

@github-actions github-actions bot added the React Core Team Opened by a member of the React Core Team label Jun 9, 2025
Copy link
Member

@rickhanlonii rickhanlonii left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sick

@sebmarkbage sebmarkbage force-pushed the fixsuspenselistuseid branch from 976d231 to 5edb07d Compare June 9, 2025 22:59
@react-sizebot
Copy link

Comparing: 80c03eb...5edb07d

Critical size changes

Includes critical production bundles, as well as any change greater than 2%:

Name +/- Base Current +/- gzip Base gzip Current gzip
oss-stable/react-dom/cjs/react-dom.production.js = 6.68 kB 6.68 kB = 1.83 kB 1.83 kB
oss-stable/react-dom/cjs/react-dom-client.production.js +0.10% 530.07 kB 530.58 kB +0.09% 93.57 kB 93.65 kB
oss-experimental/react-dom/cjs/react-dom.production.js = 6.69 kB 6.69 kB = 1.83 kB 1.83 kB
oss-experimental/react-dom/cjs/react-dom-client.production.js +0.08% 651.16 kB 651.67 kB +0.07% 114.70 kB 114.77 kB
facebook-www/ReactDOM-prod.classic.js +0.07% 676.11 kB 676.61 kB +0.07% 118.97 kB 119.05 kB
facebook-www/ReactDOM-prod.modern.js +0.08% 666.39 kB 666.89 kB +0.07% 117.36 kB 117.44 kB

Significant size changes

Includes any change greater than 0.2%:

(No significant changes)

Generated by 🚫 dangerJS against 5edb07d

@sebmarkbage sebmarkbage merged commit c38e268 into facebook:main Jun 9, 2025
241 checks passed
github-actions bot pushed a commit that referenced this pull request Jun 9, 2025
Includes #31412.

The issue is that `pushTreeFork` stores some global state when reconcile
children. This gets popped by `popTreeContext` in `completeWork`.
Normally `completeWork` returns its own `Fiber` again if it wants to do
a second pass which will call `pushTreeFork` again in the next pass.
However, `SuspenseList` doesn't return itself, it returns the next child
to work on.

The fix is to keep track of the count and push it again it when we
return the next child to attempt.

There are still some outstanding issues with hydration. Like the
backwards test still has the wrong behavior in it because it hydrates
backwards and so it picks up the DOM nodes in reverse order.
`tail="hidden"` also doesn't work correctly.

There's also another issue with `useId` and `AsyncIterable` in
SuspenseList when there's an unknown number of children. We don't
support those showing one at a time yet though so it's not an issue yet.
To fix it we need to add variable total count to the `useId` algorithm.
E.g. by falling back to varint encoding.

---------

Co-authored-by: Rick Hanlon <rickhanlonii@fb.com>
Co-authored-by: Ricky <rickhanlonii@gmail.com>

DiffTrain build for [c38e268](c38e268)
github-actions bot pushed a commit that referenced this pull request Jun 9, 2025
Includes #31412.

The issue is that `pushTreeFork` stores some global state when reconcile
children. This gets popped by `popTreeContext` in `completeWork`.
Normally `completeWork` returns its own `Fiber` again if it wants to do
a second pass which will call `pushTreeFork` again in the next pass.
However, `SuspenseList` doesn't return itself, it returns the next child
to work on.

The fix is to keep track of the count and push it again it when we
return the next child to attempt.

There are still some outstanding issues with hydration. Like the
backwards test still has the wrong behavior in it because it hydrates
backwards and so it picks up the DOM nodes in reverse order.
`tail="hidden"` also doesn't work correctly.

There's also another issue with `useId` and `AsyncIterable` in
SuspenseList when there's an unknown number of children. We don't
support those showing one at a time yet though so it's not an issue yet.
To fix it we need to add variable total count to the `useId` algorithm.
E.g. by falling back to varint encoding.

---------

Co-authored-by: Rick Hanlon <rickhanlonii@fb.com>
Co-authored-by: Ricky <rickhanlonii@gmail.com>

DiffTrain build for [c38e268](c38e268)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CLA Signed React Core Team Opened by a member of the React Core Team
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants