dillon1000/react
Commit
Browse files Add parentEnter/parentExit props to ViewTransition (#36690)
An alternative to https://github.com/facebook/react/pull/36135
___
Adds experimental support for `parentEnter` and `parentExit` on nested
`<ViewTransition>` components, so descendants can animate when an
ancestor boundary enters or exits.
This is gated behind the `enableViewTransitionParentEnterExit` feature
flag.
Addresses the use case of animating individual items in a list (such as
sliding inactive feed posts off-screen) when a parent `<ViewTransition>`
is the one being added or removed during the update.
Today, `exit`/ `enter` only fire on the `<ViewTransition>` that was
directly mounted or unmounted. Nested boundaries in the same subtree are
not visited for their own `exit`/`enter` when the whole tree goes away
as one unit, which is usually what you want. But some cases need an
explicit opt-in to nested animations.
This PR adds `parentEnter`/`parentExit`, and their handlers
`onParentEnter`/`onParentExit`. When an ancestor runs a real `enter` or
`exit`, React walks descendants and activates boundaries that define the
nested props. This only continues through `<ViewTransition>` nodes that
define `parentEnter` / `parentExit` / `onParentEnter` / `onParentExit` /
`onGestureParentEnter` / `onGestureParentExit`, otherwise the chaining
stops. A boundary’s own `enter`/`exit` still do not run when only an
ancestor animates. So it is possible to have different animations on the
same `<ViewTransition>` for `enter` vs `parentEnter`.
```jsx
function ExampleOnAncestorExit() {
return (
// This boundary exits — starts the parentExit walk
<ViewTransition exit="panel-exit">
<div>
{/* ✓ Activates: parentExit set. Walk continues inside */}
<ViewTransition parentExit="slide-out">
<div>
{/* ✗ parentEnter is not consulted on an exit walk */}
<ViewTransition parentEnter="slide-in">
...
</ViewTransition>
{/* ✗ Chain broken: no parentExit or onParentExit */}
<ViewTransition>
<div>
{/* ✗ Never reached on this path, blocked by parent above */}
<ViewTransition parentExit="slide-out">
...
</ViewTransition>
</div>
</ViewTransition>
{/* ✓ Handler-only chain: onParentExit continues the walk */}
<ViewTransition onParentExit={() => animateOut()}>
<ViewTransition onParentExit={() => animateDeepOut()}>
...
</ViewTransition>
</ViewTransition>
{/* ✓ Activates: sibling under the chain */}
<ViewTransition parentExit="slide-out">
...
</ViewTransition>
</div>
</ViewTransition>
</div>
</ViewTransition>
);
}
```Changed paths17 files
First-parent comparisonfixtures/view-transition/src/components/NestedParentExit.css AddedA fixtures/view-transition/src/components/NestedParentExit.js AddedM fixtures/view-transition/src/components/Page.js ModifiedM packages/react-dom/src/__tests__/ReactDOMViewTransition-test.js ModifiedM packages/react-reconciler/src/ReactFiberApplyGesture.js ModifiedM packages/react-reconciler/src/ReactFiberCommitViewTransitions.js ModifiedM packages/react-reconciler/src/ReactFiberCompleteWork.js ModifiedM packages/react-reconciler/src/ReactFiberFlags.js ModifiedM packages/shared/ReactFeatureFlags.js ModifiedM packages/shared/ReactTypes.js ModifiedM packages/shared/forks/ReactFeatureFlags.native-fb.js ModifiedM packages/shared/forks/ReactFeatureFlags.native-oss.js ModifiedM packages/shared/forks/ReactFeatureFlags.test-renderer.js ModifiedM packages/shared/forks/ReactFeatureFlags.test-renderer.native-fb.js ModifiedM packages/shared/forks/ReactFeatureFlags.test-renderer.www.js ModifiedM packages/shared/forks/ReactFeatureFlags.www-dynamic.js ModifiedM packages/shared/forks/ReactFeatureFlags.www.js ModifiedPatch
Files changed
Rendering syntax-highlighted changes…