-
Notifications
You must be signed in to change notification settings - Fork 47k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Selective Hydration #16880
Selective Hydration #16880
Conversation
ReactDOM: size: 0.0%, gzip: 0.0% Details of bundled changes.Comparing: a06d181...46df9f1 react-dom
react-reconciler
|
d934ed3
to
6dd28ce
Compare
6dd28ce
to
46df9f1
Compare
} | ||
break; | ||
case SuspenseComponent: | ||
flushSync(() => scheduleWork(fiber, Sync)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I find the methods that automatically flush at the end confusing unless they are at the bottom of the stack. In the work loop I've started to prefer using two separate calls, one to queue the sync work and a second explicit call that flushes it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yea I also don't like the closure. I would've done it that way but didn't feel justified to move this whole function into WorkLoop. Although the split between WorkLoop and Reconciler is a bit arbitrary right now. Reconciler is effectively just a smaller set of exposed functions from WorkLoop.
let root: FiberRoot = fiber.stateNode; | ||
if (root.hydrate) { | ||
// Flush the first scheduled "update". | ||
flushRoot(root, root.firstPendingTime); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah this is kind of weird but it makes sense :D
I suppose the other way to model this is, when hydrating, immediately commit the root in a dehydrated state.
Because hydration in concurrent mode is yieldy, we can switch hydration priority when new events come in. Selective Hydration gives us the ability to increase priority of roots and suspense boundaries based on what is being interacted with.
Discrete events are replayed in order. They are based an intentional user action so they normally have pretty high priority.
Replaying has some quirks given that we don't know if preventDefault will be called or not. Normally we allow the default behavior. However, a lot of times we'll already have received the data necessary to unblock a boundary. I.e. we're CPU bound.
This PR attempts to first synchronously hydrate the path to the discrete target. Only if that fails, do we create a queue to be replayed later.
Currently, hydration of boundaries bump to Normal pri once Suspense thennables resolve which is a bug. However, we probably also want these thennables to schedule work at even higher priority if they're blocking discrete events. I'll do that in a follow up.