main
Commits on Apr 22, 2022
-
forwardRef et al shouldn't affect if props reused (#24421)
We don't have strong guarantees that the props object is referentially equal during updates where we can't bail out anyway — like if the props are shallowly equal, but there's a local state or context update in the same batch. However, as a principle, we should aim to make the behavior consistent across different ways of memoizing a component. For example, React.memo has a different internal Fiber layout if you pass a normal function component (SimpleMemoComponent) versus if you pass a different type like forwardRef (MemoComponent). But this is an implementation detail. Wrapping a component in forwardRef (or React.lazy, etc) shouldn't affect whether the props object is reused during a bailout. Co-authored-by: Mateusz Burzyński <[email protected]>
Commits on Apr 21, 2022
-
Fix: useDeferredValue should reuse previous value (#24413)
During an urgent update, useDeferredValue should reuse the previous value. The regression test I added shows that it was reverting to the initial value instead. The cause of the bug was trivial: the update path doesn't update the hook's `memoizedState` field. Only the mount path. None of the existing tests happened to catch this because to trigger the bug, you have to do an urgent update that isn't the first update after initial render. In all of the existing tests that included an urgent update, it was the first update, so the "previous" value and the initial value happened to be the same thing.
Commits on Apr 20, 2022
-
Suppress hydration warnings when a preceding sibling suspends (#24404)
* Add failing test case for #24384 If a components suspends during hydration we expect there to be mismatches with server rendered HTML but we were not always supressing warning messages related to these expected mismatches * Mark hydration as suspending on every thrownException previously hydration would only be marked as supsending when a genuine error was thrown. This created an opportunity for a hydration mismatch that would warn after which later hydration mismatches would not lead to warnings. By moving the marker check earlier in the thrownException function we get the hydration context to enter the didSuspend state on both error and thrown promise cases which eliminates this gap. * Fix failing test related to client render fallbacks This test was actually subject to the project identified in the issue fixed in this branch. After fixing the underlying issue the assertion logic needed to change to pick the right warning which now emits after hydration successfully completes on promise resolution. I changed the container type to 'section' to make the error message slightly easier to read/understand (for me) * Only mark didSuspend on suspense path For unknown reasons the didSuspend was being set only on the error path and nto the suspense path. The original change hoisted this to happen on both paths. This change moves the didSuspend call to the suspense path only. This appears to be a noop because if the error path marked didSuspend it would suppress later warnings but if it does not the warning functions themsevles do that suppression (after the first one which necessarily already happened) * gate test on hydration fallback flags * refactor didSuspend to didSuspendOrError the orignial behavior applied the hydration warning bailout to error paths only. originally I moved it to Suspense paths only but this commit restores it to both paths and renames the marker function as didThrow rather than didSuspend The logic here is that for either case if we get a mismatch in hydration we want to warm up components but effectively consider the hydration for this boundary halted * factor tests to assert different behavior between prod and dev * add DEV suffix to didSuspendOrError to better indicate this feature should only affect dev behavior * move tests back to ReactDOMFizzServer-test * fix comment casing * drop extra flag gates in tests * add test for user error case * remove unnecessary gate * Make test better it now has an intentional client mismatch that would error if there wasn't suppression brought about by the earlier error. when it client renders it has the updated value not found in the server response but we do not see a hydration warning because it was superseded by the thrown error in that render
-
Land enableClientRenderFallbackOnHydrationMismatch (#24410)
This flag is already enabled on all relevant surfaces. We can remove it.
-
Land enableSelectiveHydration flag (#24406)
This flag is already enabled on all relevant surfaces. We can remove it.
-
Land enableClientRenderFallbackOnTextMismatch flag (#24405)
This flag is already enabled on all relevant surfaces. We can remove it.
-
Land enableLazyElements flag (#24407)
This flag is already enabled on all relevant surfaces. We can remove it.
Commits on Apr 19, 2022
-
Bugfix: In legacy mode, call suspended tree's unmount effects when it…
… is deleted (#24400) * Bug: Missing unmount when suspended tree deleted When a suspended tree switches to a fallback, we unmount the effects. If the suspended tree is then deleted, there's a guard to prevent us from unmounting the effects again. However, in legacy mode, we don't unmount effects when a tree suspends. So if the suspended tree is then deleted, we do need to unmount the effects. We're missing a check for legacy/concurrent mode. * Fix: Unmount suspended tree when it is deleted
Commits on Apr 16, 2022
Commits on Apr 15, 2022
Commits on Apr 14, 2022
-
don't stringify objects for console log second render (#24373)
Fixes #24302 based on #24306. --- The current implementation for strict mode double logging stringiness and dims the second log. However, because we stringify everything, including objects, this causes objects to be logged as `[object Object]` etc. This PR creates a new function that formats console log arguments with a specified style. It does this by: 1. The first param is a string that contains %c: Bail out and return the args without modifying the styles. We don't want to affect styles that the developer deliberately set. 2. The first param is a string that doesn't contain %c but contains string formatting: `[`%c${args[0]}`, style, ...args.slice(1)]` Note: we assume that the string formatting that the developer uses is correct. 3. The first param is a string that doesn't contain string formatting OR is not a string: Create a formatting string where: - boolean, string, symbol -> %s - number -> %f OR %i depending on if it's an int or float - default -> %o --- Co-authored-by: Billy Janitsch <[email protected]>
Commits on Apr 13, 2022
-
Rename react-dom/testing to react-dom/unstable_testing in yarn build-…
…for-devtools (#24364) The shell package wasn't compiling because yarn build-for-devtools was incorrect. The react-dom/test package was renamed to react-dom/unstable_testing. This PR fixes this in the package.json. Note: Adding packages to the yarn build-for-devtools command isn't great in the long run. Eventually we should make devtools have its own build script.
Commits on Apr 12, 2022
-
Fix typo that happened during rebasing
I changed the type of this functions returned value but forgot to change the check. It happens to work before anyway, because eventually the interleaved updates will get transferred at the beginning of the next render phase. But this is more logically consistent.
-
Bugfix: Fix race condition between interleaved and non-interleaved up…
…dates (#24353) * Regression test: Interleaved update race condition Demonstrates the bug reported in #24350. * Bugfix: Last update wins, even if interleaved "Interleaved" updates are updates that are scheduled while a render is already in progress. We put these on a special queue so that they don't get processed during the current render. Then we transfer them to the "real" queue after the render has finished. There was a race condition where an update is received after the render has finished but before the interleaved update queue had been transferred, causing the updates to be queued in the wrong order. The fix I chose is to check if the interleaved updates queue is empty before adding any update to the real queue. If it's not empty, then the new update must also be treated as interleaved.
-
[Transition Tracing] Add Offscreen Queue (#24341)
Adds an Offscreen Queue. We use the offscreen queue to store not yet processed transitions. During the commit phase, we will add these transitions to the transitions field in memoizedState (in the subsequent PR) and clear the transitions field in the updateQueue
-
Fix suspense fallback throttling (#24253)
* fix suspense throttling * fix lint * Tweak tests + another test Co-authored-by: Dan Abramov <[email protected]>
-
Match bundle.name and match upper case entry points (#24346)
Fix matching in the build script. It's possible to provide a custom bundle name in the case we build deep imports. We should match those names as a convenience. The script also calls toLowerCase on requested names but some entries have upper case now.
Commits on Apr 11, 2022
-
[Transition Tracing] Add transition to OffscreenState and pendingSusp…
…enseBoundaries to RootState (#24340) In this PR we: Add transitions boilerplate to the OffscreenState. The transitions field will be null on initiation. During the commit phase, if there are any new transitions, we will add any new transitions (either as a result of a transition occurring or a parent suspense boundary completing) to the transitions field. Once the suspense boundary resolves, we no longer need to store the transitions on the boundary, so we can put this field on the Offscreen memoized state Add pendingSuspenseBoundaries boilerplate to the RootState. This field starts as null. During the commit phase, if a suspense boundary has either gone from fallback to resolved or from resolved to fallback, we will create a new Map if there isn't one, and if there is, we will add (if the boundary is a fallback) or remove the suspense boundary (if the boundary has resolved) from the map. Add an optional name field to the Suspense boundary
-
Previously, we were only adding the passive flag when we add the Visibility flag, which is only set when we go from primary to fallback. Now, we add the passive flag BOTH when we go from primary to fallback and from fallback to primary. An alternate solution is to add the passive flag in the same place as the visibility flag in the offscreen complete phase (rather than the suspense complete phase), but this feature is currently only for suspense, and offscreen can be used in different ways, so for now we add the passive flag only in the suspense component's complete phase. We might want to revisit this later when we think about how offscreen should work with transition tracing.
-
fix pushTransition for transition tracing (#24338)
We forgot to move pushTransition out from the enableCache flag in #24321 in a place that both transition tracing and cache need to push transitions. Move it out from behind the enableCache to prepare for the next PRs.
-
[eslint-plugin-exhaustive-deps] Fix exhaustive deps check for unstab…
…le vars (#24343) * Fix exhaustive deps for unstable vars * Fix formatting * Optimise iterations * Fix linting
-
Point useSubscription to useSyncExternalStore shim (#24289)
* Point useSubscription to useSyncExternalStore shim * Update tests * Update README * Ad hoc case
-
-
-
-
Fix infinite update loop that happens when an unmemoized value is pas…
…sed to useDeferredValue (#24247) * Fix infinite loop if unmemoized val passed to uDV The current implementation of useDeferredValue will spawn a new render any time the input value is different from the previous one. So if you pass an unmemoized value (like an inline object), it will never stop spawning new renders. The fix is to only defer during an urgent render. If we're already inside a transition, retry, offscreen, or other non-urgen render, then we can use the latest value. * Temporarily disable "long nested update" warning DevTools' timeline profiler warns if an update inside a layout effect results in an expensive re-render. However, it misattributes renders that are spawned from a sync render at lower priority. This affects the new implementation of useDeferredValue but it would also apply to things like Offscreen. It's not obvious to me how to fix this given how DevTools models the idea of a "nested update" so I'm disabling the warning for now to unblock the bugfix for useDeferredValue.
-
[Fizz] Pipeable Stream Perf (#24291)
* Add fixture for comparing baseline render perf for renderToString and renderToPipeableStream Modified from ssr2 and https://github.com/SuperOleg39/react-ssr-perf-test * Implement buffering in pipeable streams The previous implementation of pipeable streaming (Node) suffered some performance issues brought about by the high chunk counts and innefficiencies with how node streams handle this situation. In particular the use of cork/uncork was meant to alleviate this but these methods do not do anything unless the receiving Writable Stream implements _writev which many won't. This change adopts the view based buffering techniques previously implemented for the Browser execution context. The main difference is the use of backpressure provided by the writable stream which is not implementable in the other context. Another change to note is the use of standards constructs like TextEncoder and TypedArrays. * Implement encodeInto during flushCompletedQueues encodeInto allows us to write directly to the view buffer that will end up getting streamed instead of encoding into an intermediate buffer and then copying that data.
Commits on Apr 9, 2022
-
add transition tracing transitions stack (#24321)
Added a transitions stack for to keep track of which transitions are still happening for the current boundary. * On the root, we will get all transitions that have been initiated for the corresponding lanes. * Whenever we encounter a suspended boundary, we will add all transitions on the stack onto the boundary * Whenever we encounter a boundary that just unsuspended, we will add all transitions on the boundary onto the stack A transition will be considered complete when there are no boundaries that have the associated transition
Commits on Apr 8, 2022
-
add pendingPassiveTransitions (#24320)
Add pendingPassiveTransitions work loop module level variable. Because workInProgressTransitions might change before we process it in the passive effects, we introduce a new variable, pendingPassiveTransitions, where we store the transitions until we can actually process them in the commit phase.
-
remove console.error in ReactFiberLane (#24319)
We changed the implementation of root.transitionLanes so that, if there is no transitions for a given lane, we use null instead of an array. This means that this error is no longer valid, so we are removing it
-
Fix: Don't call cWU if already unmounted
When a tree goes offscreen, we unmount all the effects just like we would in a normal deletion. (Conceptually it _is_ a deletion; we keep the fiber around so we can reuse its state if the tree mounts again.) If an offscreen component gets deleted "for real", we shouldn't unmount it again. The fix is to track on the stack whether we're inside a hidden tree. We already had a stack variable for this purpose, called `offscreenSubtreeWasHidden`, in another part of the commit phase, so I reused that variable instead of creating a new one. (The name is a bit confusing: "was" refers to the current tree before this commit. So, the "previous current".) Co-authored-by: dan <[email protected]>

