Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
163 changes: 103 additions & 60 deletions packages/react-reconciler/src/ReactFiberCommitViewTransitions.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,15 +71,40 @@ export let viewTransitionCancelableChildren: null | Array<
Instance | string | Props,
> = null; // tupled array where each entry is [instance: Instance, oldName: string, props: Props]

export function setViewTransitionCancelableChildren(
children: null | Array<Instance | string | Props>,
export function pushViewTransitionCancelableScope(): null | Array<
Instance | string | Props,
> {
const prevChildren = viewTransitionCancelableChildren;
viewTransitionCancelableChildren = null;
return prevChildren;
}

export function popViewTransitionCancelableScope(
prevChildren: null | Array<Instance | string | Props>,
): void {
viewTransitionCancelableChildren = children;
viewTransitionCancelableChildren = prevChildren;
}

let viewTransitionHostInstanceIdx = 0;

function applyViewTransitionToHostInstances(
export function applyViewTransitionToHostInstances(
child: null | Fiber,
name: string,
className: ?string,
collectMeasurements: null | Array<InstanceMeasurement>,
stopAtNestedViewTransitions: boolean,
): boolean {
viewTransitionHostInstanceIdx = 0;
return applyViewTransitionToHostInstancesRecursive(
child,
name,
className,
collectMeasurements,
stopAtNestedViewTransitions,
);
}

function applyViewTransitionToHostInstancesRecursive(
child: null | Fiber,
name: string,
className: ?string,
Expand Down Expand Up @@ -128,7 +153,7 @@ function applyViewTransitionToHostInstances(
// inner most one is the one that handles the update.
} else {
if (
applyViewTransitionToHostInstances(
applyViewTransitionToHostInstancesRecursive(
child.child,
name,
className,
Expand Down Expand Up @@ -207,7 +232,6 @@ function commitAppearingPairViewTransitions(placement: Fiber): void {
if (className !== 'none') {
// We found a new appearing view transition with the same name as this deletion.
// We'll transition between them.
viewTransitionHostInstanceIdx = 0;
const inViewport = applyViewTransitionToHostInstances(
child.child,
name,
Expand Down Expand Up @@ -242,7 +266,6 @@ export function commitEnterViewTransitions(placement: Fiber): void {
state.paired ? props.share : props.enter,
);
if (className !== 'none') {
viewTransitionHostInstanceIdx = 0;
const inViewport = applyViewTransitionToHostInstances(
placement.child,
name,
Expand Down Expand Up @@ -310,7 +333,6 @@ function commitDeletedPairViewTransitions(deletion: Fiber): void {
);
if (className !== 'none') {
// We found a new appearing view transition with the same name as this deletion.
viewTransitionHostInstanceIdx = 0;
const inViewport = applyViewTransitionToHostInstances(
child.child,
name,
Expand Down Expand Up @@ -361,7 +383,6 @@ export function commitExitViewTransitions(deletion: Fiber): void {
pair !== undefined ? props.share : props.exit,
);
if (className !== 'none') {
viewTransitionHostInstanceIdx = 0;
const inViewport = applyViewTransitionToHostInstances(
deletion.child,
name,
Expand Down Expand Up @@ -449,7 +470,6 @@ export function commitBeforeUpdateViewTransition(
return;
}
}
viewTransitionHostInstanceIdx = 0;
applyViewTransitionToHostInstances(
current.child,
oldName,
Expand All @@ -472,7 +492,6 @@ export function commitNestedViewTransitions(changedParent: Fiber): void {
props.layout,
);
if (className !== 'none') {
viewTransitionHostInstanceIdx = 0;
applyViewTransitionToHostInstances(
child.child,
name,
Expand Down Expand Up @@ -570,9 +589,22 @@ export function restoreNestedViewTransitions(changedParent: Fiber): void {
}
}

function cancelViewTransitionHostInstances(
currentViewTransition: Fiber,
export function cancelViewTransitionHostInstances(
child: null | Fiber,
oldName: string,
stopAtNestedViewTransitions: boolean,
): void {
viewTransitionHostInstanceIdx = 0;
cancelViewTransitionHostInstancesRecursive(
child,
oldName,
stopAtNestedViewTransitions,
);
}

function cancelViewTransitionHostInstancesRecursive(
child: null | Fiber,
oldName: string,
stopAtNestedViewTransitions: boolean,
): void {
if (!supportsMutation) {
Expand All @@ -581,10 +613,6 @@ function cancelViewTransitionHostInstances(
while (child !== null) {
if (child.tag === HostComponent) {
const instance: Instance = child.stateNode;
const oldName = getViewTransitionName(
currentViewTransition.memoizedProps,
currentViewTransition.stateNode,
);
if (viewTransitionCancelableChildren === null) {
viewTransitionCancelableChildren = [];
}
Expand All @@ -606,21 +634,42 @@ function cancelViewTransitionHostInstances(
// Skip any nested view transitions for updates since in that case the
// inner most one is the one that handles the update.
} else {
cancelViewTransitionHostInstances(
currentViewTransition,
cancelViewTransitionHostInstancesRecursive(
child.child,
oldName,
stopAtNestedViewTransitions,
);
}
child = child.sibling;
}
}

function measureViewTransitionHostInstances(
currentViewTransition: Fiber,
export function measureViewTransitionHostInstances(
parentViewTransition: Fiber,
child: null | Fiber,
name: string,
newName: string,
oldName: string,
className: ?string,
previousMeasurements: null | Array<InstanceMeasurement>,
stopAtNestedViewTransitions: boolean,
): boolean {
viewTransitionHostInstanceIdx = 0;
return measureViewTransitionHostInstancesRecursive(
parentViewTransition,
child,
newName,
oldName,
className,
previousMeasurements,
stopAtNestedViewTransitions,
);
}

function measureViewTransitionHostInstancesRecursive(
parentViewTransition: Fiber,
child: null | Fiber,
newName: string,
oldName: string,
className: ?string,
previousMeasurements: null | Array<InstanceMeasurement>,
stopAtNestedViewTransitions: boolean,
Expand Down Expand Up @@ -671,10 +720,10 @@ function measureViewTransitionHostInstances(
applyViewTransitionName(
instance,
viewTransitionHostInstanceIdx === 0
? name
? newName
: // If we have multiple Host Instances below, we add a suffix to the name to give
// each one a unique name.
name + '_' + viewTransitionHostInstanceIdx,
newName + '_' + viewTransitionHostInstanceIdx,
className,
);
}
Expand All @@ -684,10 +733,6 @@ function measureViewTransitionHostInstances(
// animating it. However, in the current model this only works if the parent also
// doesn't animate. So we have to queue these and wait until we complete the parent
// to cancel them.
const oldName = getViewTransitionName(
currentViewTransition.memoizedProps,
currentViewTransition.stateNode,
);
if (viewTransitionCancelableChildren === null) {
viewTransitionCancelableChildren = [];
}
Expand All @@ -713,11 +758,11 @@ function measureViewTransitionHostInstances(
parentViewTransition.flags |= child.flags & AffectedParentLayout;
} else {
if (
measureViewTransitionHostInstances(
currentViewTransition,
measureViewTransitionHostInstancesRecursive(
parentViewTransition,
child.child,
name,
newName,
oldName,
className,
previousMeasurements,
stopAtNestedViewTransitions,
Expand All @@ -736,6 +781,11 @@ export function measureUpdateViewTransition(
finishedWork: Fiber,
): boolean {
const props: ViewTransitionProps = finishedWork.memoizedProps;
const newName = getViewTransitionName(props, finishedWork.stateNode);
const oldName = getViewTransitionName(
current.memoizedProps,
current.stateNode,
);
const updateClassName: ?string = getViewTransitionClassName(
props.className,
props.update,
Expand All @@ -762,24 +812,21 @@ export function measureUpdateViewTransition(
if (layoutClassName === 'none') {
// If we did not update, then all changes are considered a layout. We'll
// attempt to cancel.
viewTransitionHostInstanceIdx = 0;
cancelViewTransitionHostInstances(current, finishedWork.child, true);
cancelViewTransitionHostInstances(finishedWork.child, oldName, true);
return false;
}
// We didn't update but we might still apply layout so we measure each
// instance to see if it moved or resized.
className = layoutClassName;
}
const name = getViewTransitionName(props, finishedWork.stateNode);
// If nothing changed due to a mutation, or children changing size
// and the measurements end up unchanged, we should restore it to not animate.
viewTransitionHostInstanceIdx = 0;
const previousMeasurements = current.memoizedState;
const inViewport = measureViewTransitionHostInstances(
current,
finishedWork,
finishedWork.child,
name,
newName,
oldName,
className,
previousMeasurements,
true,
Expand All @@ -799,29 +846,25 @@ export function measureNestedViewTransitions(changedParent: Fiber): void {
let child = changedParent.child;
while (child !== null) {
if (child.tag === ViewTransitionComponent) {
const current = child.alternate;
if (current !== null) {
const props: ViewTransitionProps = child.memoizedProps;
const name = getViewTransitionName(props, child.stateNode);
const className: ?string = getViewTransitionClassName(
props.className,
props.layout,
);
viewTransitionHostInstanceIdx = 0;
const inViewport = measureViewTransitionHostInstances(
current,
child,
child.child,
name,
className,
child.memoizedState,
false,
);
if ((child.flags & Update) === NoFlags || !inViewport) {
// Nothing changed.
} else {
scheduleViewTransitionEvent(child, props.onLayout);
}
const props: ViewTransitionProps = child.memoizedProps;
const name = getViewTransitionName(props, child.stateNode);
const className: ?string = getViewTransitionClassName(
props.className,
props.layout,
);
const inViewport = measureViewTransitionHostInstances(
child,
child.child,
name,
name, // Since this is unchanged, new and old name is the same.
className,
child.memoizedState,
false,
);
if ((child.flags & Update) === NoFlags || !inViewport) {
// Nothing changed.
} else {
scheduleViewTransitionEvent(child, props.onLayout);
}
} else if ((child.subtreeFlags & ViewTransitionStatic) !== NoFlags) {
measureNestedViewTransitions(child);
Expand Down
14 changes: 7 additions & 7 deletions packages/react-reconciler/src/ReactFiberCommitWork.js
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,8 @@ import {
resetAppearingViewTransitions,
trackAppearingViewTransition,
viewTransitionCancelableChildren,
setViewTransitionCancelableChildren,
pushViewTransitionCancelableScope,
popViewTransitionCancelableScope,
} from './ReactFiberCommitViewTransitions';
import {
viewTransitionMutationContext,
Expand Down Expand Up @@ -2475,14 +2476,14 @@ function commitAfterMutationEffectsOnFiber(
switch (finishedWork.tag) {
case HostRoot: {
viewTransitionContextChanged = false;
setViewTransitionCancelableChildren(null);
pushViewTransitionCancelableScope();
recursivelyTraverseAfterMutationEffects(root, finishedWork, lanes);
if (!viewTransitionContextChanged) {
// If we didn't leak any resizing out to the root, we don't have to transition
// the root itself. This means that we can now safely cancel any cancellations
// that bubbled all the way up.
const cancelableChildren = viewTransitionCancelableChildren;
setViewTransitionCancelableChildren(null);
popViewTransitionCancelableScope(null);
if (cancelableChildren !== null) {
for (let i = 0; i < cancelableChildren.length; i += 3) {
cancelViewTransitionName(
Expand Down Expand Up @@ -2533,9 +2534,8 @@ function commitAfterMutationEffectsOnFiber(
const wasMutated = (finishedWork.flags & Update) !== NoFlags;

const prevContextChanged = viewTransitionContextChanged;
const prevCancelableChildren = viewTransitionCancelableChildren;
const prevCancelableChildren = pushViewTransitionCancelableScope();
viewTransitionContextChanged = false;
setViewTransitionCancelableChildren(null);
recursivelyTraverseAfterMutationEffects(root, finishedWork, lanes);

if (viewTransitionContextChanged) {
Expand All @@ -2558,7 +2558,7 @@ function commitAfterMutationEffectsOnFiber(
prevCancelableChildren,
viewTransitionCancelableChildren,
);
setViewTransitionCancelableChildren(prevCancelableChildren);
popViewTransitionCancelableScope(prevCancelableChildren);
}
// TODO: If this doesn't end up canceled, because a parent animates,
// then we should probably issue an event since this instance is part of it.
Expand All @@ -2572,7 +2572,7 @@ function commitAfterMutationEffectsOnFiber(
);

// If this boundary did update, we cannot cancel its children so those are dropped.
setViewTransitionCancelableChildren(prevCancelableChildren);
popViewTransitionCancelableScope(prevCancelableChildren);
}

if ((finishedWork.flags & AffectedParentLayout) !== NoFlags) {
Expand Down
Loading