-
Notifications
You must be signed in to change notification settings - Fork 47.7k
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
[RFC] Add initialValue option to useDeferredValue #24369
Conversation
Comparing: bd08137...b441be7 Critical size changesIncludes critical production bundles, as well as any change greater than 2%:
Significant size changesIncludes any change greater than 0.2%: (No significant changes) |
a800512
to
2f14b06
Compare
What do you mean by progressive enhancement? |
Minor nit that the initial value can't be the value Last time I thought about in context of Retry I convinced me that it would eventually be ok only because it wouldn't apply to initial render. There's something weird about deferring the value when the thing is not visible. E.g. because it resuspended and then gets rendered again or when something is initially rendered as Offscreen. Deferring it would also deprioritize that update. You couldn't implement this in user space since the effect wouldn't fire while Offscreen to allow the second render pass. So you'd always see the initial value and then toggle it. That might be a reason for why it should be built-in but I'm not sure it makes sense to make that a two pass render rather than just going straight for the end value if that's what you're going to end up likely seeing anyway. At least first and then only fallback if that suspends. I'm also curious what you mean by progressive enhancement because for the SSR case, and the use case for the Even if it's not SSR and you want to have a lighter implementation and then React.lazy load a second implementation, I think you would want to always try the better implementation first in case it's already loaded instead of always rendering the lighter implementation and then switching. |
Maybe we need a new hook like |
Yeah that's true, the only reason I made it use the "light" value during initial render regardless of priority is to avoid a server-client mismatch, but first it should check if it's actually hydrating, too.
The first part makes sense, but why would it switch to the "light" value during an update? Seems like it's better to stay on the previous value. That's why I figured these should be the same hook, since except for server rendering the behavior is the same. Based on this feedback I think my preference is to add an |
What is the canonical one? The first one? So the second value is only for SSR/hydration or sync updates? |
Yeah to me it's similar to passing an initial value to |
It's a little weird that it wouldn't be used for transitions but I think that makes sense but probably needs a different name. |
Yeah we could warn in dev if there's a second argument but it's undefined. As opposed to a missing argument. I assume that's expressible in TypeScript.
Progressive value? |
Currently, useDeferredValue only works for updates. It will never during the initial render because there's no previous value to reuse. This means it can't be used to implement progressive enhancement. This adds an optional initialValue argument to useDeferredValue. When provided, the initial mount will use initialValue if it's during an urgent render. Otherwise it will use the latest, canonical value. During server rendering and hydration, it will always use the initialValue instead of the canonical value, regardless of priority, to avoid a hydration mismatch. The name "initial value" isn't ideal because during a non-urgent client render, it's disregarded entirely. It's more like a "lightweight" value that will later be upgraded to a "heavier" one. Needs some bikeshedding. When initialValue is omitted, the behavior is the same as today.
2f14b06
to
b441be7
Compare
Landed in #27500 |
Currently, useDeferredValue only works for updates. It will never during the initial render because there's no previous value to reuse. This means it can't be used to implement progressive enhancement.
This adds an optional initialValue argument to useDeferredValue. When provided, the initial mount will use initialValue if it's during an urgent render. Otherwise it will use the latest, canonical value.
During server rendering and hydration, it will always use the initialValue instead of the canonical value, regardless of priority, to avoid a hydration mismatch.
The name "initial value" isn't ideal because during a non-urgent client render, it's disregarded entirely. It's more like a "lightweight" value that will later be upgraded to a "heavier" one. Needs some bikeshedding.
When initialValue is omitted, the behavior is the same as today.