Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix: useDeferredValue initialValue suspends forever without switching…
… to final (#27888) Fixes a bug in the experimental `initialValue` option for `useDeferredValue` (added in #27500). If rendering the `initialValue` causes the tree to suspend, React should skip it and switch to rendering the final value instead. It should not wait for `initialValue` to resolve. This is not just an optimization, because in some cases the initial value may _never_ resolve — intentionally. For example, if the application does not provide an instant fallback state. This capability is, in fact, the primary motivation for the `initialValue` API. I mostly implemented this correctly in the original PR, but I missed some cases where it wasn't working: - If there's no Suspense boundary between the `useDeferredValue` hook and the component that suspends, and we're not in the shell of the transition (i.e. there's a parent Suspense boundary wrapping the `useDeferredValue` hook), the deferred task would get incorrectly dropped. - Similarly, if there's no Suspense boundary between the `useDeferredValue` hook and the component that suspends, and we're rendering a synchronous update, the deferred task would get incorrectly dropped. What these cases have in common is that it causes the `useDeferredValue` hook itself to be replaced by a Suspense fallback. The fix was the same for both. (It already worked in cases where there's no Suspense fallback at all, because those are handled differently, at the root.) The way I discovered this was when investigating a particular bug in Next.js that would happen during a 'popstate' transition (back/forward), but not during a regular navigation. That's because we render popstate transitions synchronously to preserve browser's scroll position — which in this case triggered the second scenario above. DiffTrain build for commit f1039be.
- Loading branch information