@@ -547,16 +547,25 @@ function applyViewTransitionToHostInstances(
547547 name : string ,
548548 collectMeasurements : null | Array < InstanceMeasurement > ,
549549 stopAtNestedViewTransitions : boolean ,
550- ) : void {
550+ ) : boolean {
551551 if ( ! supportsMutation ) {
552- return ;
552+ return false ;
553553 }
554+ let inViewport = false ;
554555 while ( child !== null ) {
555556 if ( child . tag === HostComponent ) {
556557 shouldStartViewTransition = true ;
557558 const instance : Instance = child . stateNode ;
558559 if ( collectMeasurements !== null ) {
559- collectMeasurements . push ( measureInstance ( instance ) ) ;
560+ const measurement = measureInstance ( instance ) ;
561+ collectMeasurements . push ( measurement ) ;
562+ if ( wasInstanceInViewport ( measurement ) ) {
563+ inViewport = true ;
564+ }
565+ } else if ( ! inViewport ) {
566+ if ( wasInstanceInViewport ( measureInstance ( instance ) ) ) {
567+ inViewport = true ;
568+ }
560569 }
561570 applyViewTransitionName (
562571 instance ,
@@ -579,15 +588,20 @@ function applyViewTransitionToHostInstances(
579588 // Skip any nested view transitions for updates since in that case the
580589 // inner most one is the one that handles the update.
581590 } else {
582- applyViewTransitionToHostInstances (
583- child . child ,
584- name ,
585- collectMeasurements ,
586- stopAtNestedViewTransitions ,
587- ) ;
591+ if (
592+ applyViewTransitionToHostInstances (
593+ child . child ,
594+ name ,
595+ collectMeasurements ,
596+ stopAtNestedViewTransitions ,
597+ )
598+ ) {
599+ inViewport = true ;
600+ }
588601 }
589602 child = child . sibling ;
590603 }
604+ return inViewport ;
591605}
592606
593607function restoreViewTransitionOnHostInstances (
@@ -668,8 +682,20 @@ function commitEnterViewTransitions(placement: Fiber): void {
668682 placement . stateNode ,
669683 ) ;
670684 viewTransitionHostInstanceIdx = 0 ;
671- applyViewTransitionToHostInstances ( placement . child , name , null , false ) ;
672- commitAppearingPairViewTransitions ( placement ) ;
685+ const inViewport = applyViewTransitionToHostInstances (
686+ placement . child ,
687+ name ,
688+ null ,
689+ false ,
690+ ) ;
691+ if ( ! inViewport ) {
692+ // Revert the transition names. This boundary is not in the viewport
693+ // so we won't bother animating it.
694+ restoreViewTransitionOnHostInstances ( placement . child , false ) ;
695+ // TODO: Should we still visit the children in case a named one was in the viewport?
696+ } else {
697+ commitAppearingPairViewTransitions ( placement ) ;
698+ }
673699 } else if ( ( placement . subtreeFlags & ViewTransitionStatic ) !== NoFlags ) {
674700 let child = placement . child ;
675701 while ( child !== null ) {
@@ -737,9 +763,18 @@ function commitExitViewTransitions(
737763 const props : ViewTransitionProps = deletion . memoizedProps ;
738764 const name = getViewTransitionName ( props , deletion . stateNode ) ;
739765 viewTransitionHostInstanceIdx = 0 ;
740- applyViewTransitionToHostInstances ( deletion . child , name , null , false ) ;
741-
742- if ( appearingViewTransitions !== null ) {
766+ const inViewport = applyViewTransitionToHostInstances (
767+ deletion . child ,
768+ name ,
769+ null ,
770+ false ,
771+ ) ;
772+ if ( ! inViewport ) {
773+ // Revert the transition names. This boundary is not in the viewport
774+ // so we won't bother animating it.
775+ restoreViewTransitionOnHostInstances ( deletion . child , false ) ;
776+ // TODO: Should we still visit the children in case a named one was in the viewport?
777+ } else if ( appearingViewTransitions !== null ) {
743778 const pair = appearingViewTransitions . get ( name ) ;
744779 if ( pair !== undefined ) {
745780 // We found a new appearing view transition with the same name as this deletion.
@@ -2999,9 +3034,9 @@ function commitAfterMutationEffectsOnFiber(
29993034 finishedWork . flags |= Update ;
30003035 }
30013036
3002- const inViewPort = measureUpdateViewTransition ( current , finishedWork ) ;
3037+ const inViewport = measureUpdateViewTransition ( current , finishedWork ) ;
30033038
3004- if ( ( finishedWork . flags & Update ) === NoFlags || ! inViewPort ) {
3039+ if ( ( finishedWork . flags & Update ) === NoFlags || ! inViewport ) {
30053040 // If this boundary didn't update, then we may be able to cancel its children.
30063041 // We bubble them up to the parent set to be determined later if we can cancel.
30073042 // Similarly, if old and new state was outside the viewport, we can skip it
0 commit comments