Skip to content

Commit 703ebab

Browse files
committed
Don't bother applying transitions to enter/exit that are outside the viewport
These shouldn't be visible anyway.
1 parent b8a6e2b commit 703ebab

File tree

1 file changed

+51
-16
lines changed

1 file changed

+51
-16
lines changed

packages/react-reconciler/src/ReactFiberCommitWork.js

Lines changed: 51 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -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

593607
function 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

Comments
 (0)