@@ -276,6 +276,10 @@ export let shouldFireAfterActiveInstanceBlur: boolean = false;
276276
277277export let shouldStartViewTransition : boolean = false ;
278278
279+ // This tracks named ViewTransition components found in the accumulateSuspenseyCommit
280+ // phase that might need to find deleted pairs in the beforeMutation phase.
281+ let appearingViewTransitions : Map < string , ViewTransitionState > | null = null ;
282+
279283// Used during the commit phase to track whether a parent ViewTransition component
280284// might have been affected by any mutations / relayouts below.
281285let viewTransitionContextChanged : boolean = false ;
@@ -288,7 +292,6 @@ export function commitBeforeMutationEffects(
288292 root : FiberRoot ,
289293 firstChild : Fiber ,
290294 committedLanes : Lanes ,
291- appearingViewTransitions : Map < string , ViewTransitionState > | null ,
292295) : void {
293296 focusedInstanceHandle = prepareForCommit ( root . containerInfo ) ;
294297 shouldFireAfterActiveInstanceBlur = false ;
@@ -299,19 +302,15 @@ export function commitBeforeMutationEffects(
299302 includesOnlyViewTransitionEligibleLanes ( committedLanes ) ;
300303
301304 nextEffect = firstChild ;
302- commitBeforeMutationEffects_begin (
303- isViewTransitionEligible ,
304- appearingViewTransitions ,
305- ) ;
305+ commitBeforeMutationEffects_begin ( isViewTransitionEligible ) ;
306306
307307 // We no longer need to track the active instance fiber
308308 focusedInstanceHandle = null ;
309+ // We've found any matched pairs and can now reset.
310+ appearingViewTransitions = null ;
309311}
310312
311- function commitBeforeMutationEffects_begin (
312- isViewTransitionEligible : boolean ,
313- appearingViewTransitions : Map < string , ViewTransitionState > | null ,
314- ) {
313+ function commitBeforeMutationEffects_begin ( isViewTransitionEligible : boolean ) {
315314 // If this commit is eligible for a View Transition we look into all mutated subtrees.
316315 // TODO: We could optimize this by marking these with the Snapshot subtree flag in the render phase.
317316 const subtreeMask = isViewTransitionEligible
@@ -331,7 +330,6 @@ function commitBeforeMutationEffects_begin(
331330 commitBeforeMutationEffectsDeletion (
332331 deletion ,
333332 isViewTransitionEligible ,
334- appearingViewTransitions ,
335333 ) ;
336334 }
337335 }
@@ -364,7 +362,7 @@ function commitBeforeMutationEffects_begin(
364362 isViewTransitionEligible
365363 ) {
366364 // Was previously mounted as visible but is now hidden.
367- commitExitViewTransitions ( current , appearingViewTransitions ) ;
365+ commitExitViewTransitions ( current ) ;
368366 }
369367 // Skip before mutation effects of the children because they're hidden.
370368 commitBeforeMutationEffects_complete ( isViewTransitionEligible ) ;
@@ -528,7 +526,6 @@ function commitBeforeMutationEffectsOnFiber(
528526function commitBeforeMutationEffectsDeletion (
529527 deletion : Fiber ,
530528 isViewTransitionEligible : boolean ,
531- appearingViewTransitions : Map < string , ViewTransitionState > | null ,
532529) {
533530 if ( enableCreateEventHandleAPI ) {
534531 // TODO (effects) It would be nice to avoid calling doesFiberContain()
@@ -541,7 +538,7 @@ function commitBeforeMutationEffectsDeletion(
541538 }
542539 }
543540 if ( isViewTransitionEligible ) {
544- commitExitViewTransitions ( deletion , appearingViewTransitions ) ;
541+ commitExitViewTransitions ( deletion ) ;
545542 }
546543}
547544
@@ -745,14 +742,15 @@ function commitEnterViewTransitions(placement: Fiber): void {
745742 }
746743}
747744
748- function commitDeletedPairViewTransitions (
749- deletion : Fiber ,
750- appearingViewTransitions : Map < string , ViewTransitionState > ,
751- ) : void {
752- if ( appearingViewTransitions . size === 0 ) {
745+ function commitDeletedPairViewTransitions ( deletion : Fiber ) : void {
746+ if (
747+ appearingViewTransitions === null ||
748+ appearingViewTransitions . size === 0
749+ ) {
753750 // We've found all.
754751 return ;
755752 }
753+ const pairs = appearingViewTransitions ;
756754 if ( ( deletion . subtreeFlags & ViewTransitionNamedStatic ) === NoFlags ) {
757755 // This has no named view transitions in its subtree.
758756 return ;
@@ -769,7 +767,7 @@ function commitDeletedPairViewTransitions(
769767 const props : ViewTransitionProps = child . memoizedProps ;
770768 const name = props . name ;
771769 if ( name != null && name !== 'auto' ) {
772- const pair = appearingViewTransitions . get ( name ) ;
770+ const pair = pairs . get ( name ) ;
773771 if ( pair !== undefined ) {
774772 const className : ?string = getViewTransitionClassName (
775773 props . className ,
@@ -802,23 +800,20 @@ function commitDeletedPairViewTransitions(
802800 }
803801 // Delete the entry so that we know when we've found all of them
804802 // and can stop searching (size reaches zero).
805- appearingViewTransitions . delete ( name ) ;
806- if ( appearingViewTransitions . size === 0 ) {
803+ pairs . delete ( name ) ;
804+ if ( pairs . size === 0 ) {
807805 break ;
808806 }
809807 }
810808 }
811809 }
812- commitDeletedPairViewTransitions ( child , appearingViewTransitions ) ;
810+ commitDeletedPairViewTransitions ( child ) ;
813811 }
814812 child = child . sibling ;
815813 }
816814}
817815
818- function commitExitViewTransitions (
819- deletion : Fiber ,
820- appearingViewTransitions : Map < string , ViewTransitionState > | null ,
821- ) : void {
816+ function commitExitViewTransitions ( deletion : Fiber ) : void {
822817 if ( deletion . tag === ViewTransitionComponent ) {
823818 const props : ViewTransitionProps = deletion . memoizedProps ;
824819 const name = getViewTransitionName ( props , deletion . stateNode ) ;
@@ -863,17 +858,17 @@ function commitExitViewTransitions(
863858 }
864859 if ( appearingViewTransitions !== null ) {
865860 // Look for more pairs deeper in the tree.
866- commitDeletedPairViewTransitions ( deletion , appearingViewTransitions ) ;
861+ commitDeletedPairViewTransitions ( deletion ) ;
867862 }
868863 } else if ( ( deletion . subtreeFlags & ViewTransitionStatic ) !== NoFlags ) {
869864 let child = deletion . child ;
870865 while ( child !== null ) {
871- commitExitViewTransitions ( child , appearingViewTransitions ) ;
866+ commitExitViewTransitions ( child ) ;
872867 child = child . sibling ;
873868 }
874869 } else {
875870 if ( appearingViewTransitions !== null ) {
876- commitDeletedPairViewTransitions ( deletion , appearingViewTransitions ) ;
871+ commitDeletedPairViewTransitions ( deletion ) ;
877872 }
878873 }
879874}
@@ -4813,8 +4808,13 @@ export function commitPassiveUnmountEffects(finishedWork: Fiber): void {
48134808// already in the "current" tree. Because their visibility has changed, the
48144809// browser may not have prerendered them yet. So we check the MaySuspendCommit
48154810// flag instead.
4811+ //
4812+ // Note that MaySuspendCommit and ShouldSuspendCommit also includes named
4813+ // ViewTransitions so that we know to also visit those to collect appearing
4814+ // pairs.
48164815let suspenseyCommitFlag = ShouldSuspendCommit ;
48174816export function accumulateSuspenseyCommit ( finishedWork : Fiber ) : void {
4817+ appearingViewTransitions = null ;
48184818 accumulateSuspenseyCommitOnFiber ( finishedWork ) ;
48194819}
48204820
@@ -4893,6 +4893,29 @@ function accumulateSuspenseyCommitOnFiber(fiber: Fiber) {
48934893 }
48944894 break ;
48954895 }
4896+ case ViewTransitionComponent : {
4897+ if ( enableViewTransition ) {
4898+ if ( ( fiber . flags & suspenseyCommitFlag ) !== NoFlags ) {
4899+ const props : ViewTransitionProps = fiber . memoizedProps ;
4900+ const name : ?string | 'auto' = props . name ;
4901+ if ( name != null && name !== 'auto' ) {
4902+ // This is a named ViewTransition being mounted or reappearing. Let's add it to
4903+ // the map so we can match it with deletions later.
4904+ if ( appearingViewTransitions === null ) {
4905+ appearingViewTransitions = new Map ( ) ;
4906+ }
4907+ // Reset the pair in case we didn't end up restoring the instance in previous commits.
4908+ // This shouldn't really happen anymore but just in case. We could maybe add an invariant.
4909+ const instance : ViewTransitionState = fiber . stateNode ;
4910+ instance . paired = null ;
4911+ appearingViewTransitions . set ( name , instance ) ;
4912+ }
4913+ }
4914+ recursivelyAccumulateSuspenseyCommit ( fiber ) ;
4915+ break ;
4916+ }
4917+ // Fallthrough
4918+ }
48964919 default : {
48974920 recursivelyAccumulateSuspenseyCommit ( fiber ) ;
48984921 }
0 commit comments