dillon1000/react
Commit
Browse files [Fiber] Trigger default transition indicator if needed (#33160)
Stacked on #33159. This implements `onDefaultTransitionIndicator`. The sequence is: 1) In `markRootUpdated` we schedule Transition updates as needing `indicatorLanes` on the root. This tracks the lanes that currently need an indicator to either start or remain going until this lane commits. 2) Track mutations during any commit. We use the same hook that view transitions use here but instead of tracking it just per view transition scope, we also track a global boolean for the whole root. 3) If a sync/default commit had any mutations, then we clear the indicator lane for the `currentEventTransitionLane`. This requires that the lane is still active while we do these commits. See #33159. In other words, a sync update gets associated with the current transition and it is assumed to be rendering the loading state for that corresponding transition so we don't need a default indicator for this lane. 4) At the end of `processRootScheduleInMicrotask`, right before we're about to enter a new "event transition lane" scope, it is no longer possible to render any more loading states for the current transition lane. That's when we invoke `onDefaultTransitionIndicator` for any roots that have new indicator lanes. 5) When we commit, we remove the finished lanes from `indicatorLanes` and once that reaches zero again, then we can clean up the default indicator. This approach means that you can start multiple different transitions while an indicator is still going but it won't stop/restart each time. Instead, it'll wait until all are done before stopping. Follow ups: - [x] Default updates are currently not enough to cancel because those aren't flush in the same microtask. That's unfortunate. #33186 - [x] Handle async actions before the setState. Since these don't necessarily have a root this is tricky. #33190 - [x] Disable for `useDeferredValue`. ~Since it also goes through `markRootUpdated` and schedules a Transition lane it'll get a default indicator even though it probably shouldn't have one.~ EDIT: Turns out this just works because it doesn't go through `markRootUpdated` when work is left behind. - [x] Implement built-in DOM version by default. #33162
Changed paths9 files
First-parent comparisonpackages/react-noop-renderer/src/createReactNoop.js ModifiedM packages/react-reconciler/src/ReactFiberCommitWork.js ModifiedM packages/react-reconciler/src/ReactFiberLane.js ModifiedM packages/react-reconciler/src/ReactFiberMutationTracking.js ModifiedM packages/react-reconciler/src/ReactFiberRoot.js ModifiedM packages/react-reconciler/src/ReactFiberRootScheduler.js ModifiedM packages/react-reconciler/src/ReactFiberWorkLoop.js ModifiedM packages/react-reconciler/src/ReactInternalTypes.js ModifiedA packages/react-reconciler/src/__tests__/ReactDefaultTransitionIndicator-test.js AddedPatch
Files changed
Rendering syntax-highlighted changes…