Skip to content

Commit 42a57ea

Browse files
authored
Merge ViewTransition layout/onLayout props into update/onUpdate (#32723)
We currently have the ability to have a separate animation for a ViewTransition that relayouts but doesn't actually have any internal mutations. This can be useful if you want to separate just a move from for example flashing an update. However, we're concerned that this might be more confusion than its worth because subtle differences in mutations can cause it to trigger the other case. The existence of the property name might also make you start looking for it to solve something that it's not meant for. We already fallback to using the "update" property if it exists but layout doesn't. So if we ever decide to add this back it would backwards compatible. We've also shown in implementation that it can work.
1 parent 04bf10e commit 42a57ea

File tree

4 files changed

+16
-114
lines changed

4 files changed

+16
-114
lines changed

packages/react-reconciler/src/ReactFiberApplyGesture.js

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,7 @@ function applyNestedViewTransition(child: Fiber): void {
308308
const name = getViewTransitionName(props, state);
309309
const className: ?string = getViewTransitionClassName(
310310
props.className,
311-
props.layout,
311+
props.update,
312312
);
313313
if (className !== 'none') {
314314
const clones = state.clones;
@@ -335,17 +335,13 @@ function applyUpdateViewTransition(current: Fiber, finishedWork: Fiber): void {
335335
// we would use. However, since this animation is going in reverse we actually
336336
// want the props from "current" since that's the class that would've won if
337337
// it was the normal direction. To preserve the same effect in either direction.
338-
let className: ?string = getViewTransitionClassName(
338+
const className: ?string = getViewTransitionClassName(
339339
newProps.className,
340340
newProps.update,
341341
);
342342
if (className === 'none') {
343-
className = getViewTransitionClassName(newProps.className, newProps.layout);
344-
if (className === 'none') {
345-
// If both update and layout are both "none" then we don't have to
346-
// apply a name. Since we won't animate this boundary.
347-
return;
348-
}
343+
// If update is "none" then we don't have to apply a name. Since we won't animate this boundary.
344+
return;
349345
}
350346
const clones = state.clones;
351347
// If there are no clones at this point, that should mean that there are no

packages/react-reconciler/src/ReactFiberCommitViewTransitions.js

Lines changed: 11 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -469,17 +469,13 @@ export function commitBeforeUpdateViewTransition(
469469
// For example, if update="foo" layout="none" and it turns out this was
470470
// a layout only change, then the "foo" class will be applied even though
471471
// it was not actually an update. Which is a bug.
472-
let className: ?string = getViewTransitionClassName(
472+
const className: ?string = getViewTransitionClassName(
473473
newProps.className,
474474
newProps.update,
475475
);
476476
if (className === 'none') {
477-
className = getViewTransitionClassName(newProps.className, newProps.layout);
478-
if (className === 'none') {
479-
// If both update and layout are both "none" then we don't have to
480-
// apply a name. Since we won't animate this boundary.
481-
return;
482-
}
477+
// If update is "none" then we don't have to apply a name. Since we won't animate this boundary.
478+
return;
483479
}
484480
applyViewTransitionToHostInstances(
485481
current.child,
@@ -500,7 +496,7 @@ export function commitNestedViewTransitions(changedParent: Fiber): void {
500496
const name = getViewTransitionName(props, child.stateNode);
501497
const className: ?string = getViewTransitionClassName(
502498
props.className,
503-
props.layout,
499+
props.update,
504500
);
505501
if (className !== 'none') {
506502
applyViewTransitionToHostInstances(
@@ -590,61 +586,6 @@ export function restoreNestedViewTransitions(changedParent: Fiber): void {
590586
}
591587
}
592588

593-
export function cancelViewTransitionHostInstances(
594-
child: null | Fiber,
595-
oldName: string,
596-
stopAtNestedViewTransitions: boolean,
597-
): void {
598-
viewTransitionHostInstanceIdx = 0;
599-
cancelViewTransitionHostInstancesRecursive(
600-
child,
601-
oldName,
602-
stopAtNestedViewTransitions,
603-
);
604-
}
605-
606-
function cancelViewTransitionHostInstancesRecursive(
607-
child: null | Fiber,
608-
oldName: string,
609-
stopAtNestedViewTransitions: boolean,
610-
): void {
611-
if (!supportsMutation) {
612-
return;
613-
}
614-
while (child !== null) {
615-
if (child.tag === HostComponent) {
616-
const instance: Instance = child.stateNode;
617-
if (viewTransitionCancelableChildren === null) {
618-
viewTransitionCancelableChildren = [];
619-
}
620-
viewTransitionCancelableChildren.push(
621-
instance,
622-
oldName,
623-
child.memoizedProps,
624-
);
625-
viewTransitionHostInstanceIdx++;
626-
} else if (
627-
child.tag === OffscreenComponent &&
628-
child.memoizedState !== null
629-
) {
630-
// Skip any hidden subtrees. They were or are effectively not there.
631-
} else if (
632-
child.tag === ViewTransitionComponent &&
633-
stopAtNestedViewTransitions
634-
) {
635-
// Skip any nested view transitions for updates since in that case the
636-
// inner most one is the one that handles the update.
637-
} else {
638-
cancelViewTransitionHostInstancesRecursive(
639-
child.child,
640-
oldName,
641-
stopAtNestedViewTransitions,
642-
);
643-
}
644-
child = child.sibling;
645-
}
646-
}
647-
648589
export function measureViewTransitionHostInstances(
649590
parentViewTransition: Fiber,
650591
child: null | Fiber,
@@ -792,40 +733,14 @@ export function measureUpdateViewTransition(
792733
const state: ViewTransitionState = newFiber.stateNode;
793734
const newName = getViewTransitionName(props, state);
794735
const oldName = getViewTransitionName(oldFiber.memoizedProps, state);
795-
const updateClassName: ?string = getViewTransitionClassName(
736+
// Whether it ends up having been updated or relayout we apply the update class name.
737+
const className: ?string = getViewTransitionClassName(
796738
props.className,
797739
props.update,
798740
);
799-
const layoutClassName: ?string = getViewTransitionClassName(
800-
props.className,
801-
props.layout,
802-
);
803-
let className: ?string;
804-
if (updateClassName === 'none') {
805-
if (layoutClassName === 'none') {
806-
// If both update and layout class name were none, then we didn't apply any
807-
// names in the before update phase so we shouldn't now neither.
808-
return false;
809-
}
810-
// We don't care if this is mutated or children layout changed, but we still
811-
// measure each instance to see if it moved and therefore should apply layout.
812-
finishedWork.flags &= ~Update;
813-
className = layoutClassName;
814-
} else if ((finishedWork.flags & Update) !== NoFlags) {
815-
// It was updated and we have an appropriate class name to apply.
816-
className = updateClassName;
817-
} else {
818-
if (layoutClassName === 'none') {
819-
// If we did not update, then all changes are considered a layout. We'll
820-
// attempt to cancel.
821-
// This should use the Fiber that got names applied in the snapshot phase
822-
// since those are the ones we're trying to cancel.
823-
cancelViewTransitionHostInstances(oldFiber.child, oldName, true);
824-
return false;
825-
}
826-
// We didn't update but we might still apply layout so we measure each
827-
// instance to see if it moved or resized.
828-
className = layoutClassName;
741+
if (className === 'none') {
742+
// If update is "none" then we don't have to apply a name. Since we won't animate this boundary.
743+
return false;
829744
}
830745
// If nothing changed due to a mutation, or children changing size
831746
// and the measurements end up unchanged, we should restore it to not animate.
@@ -873,7 +788,7 @@ export function measureNestedViewTransitions(
873788
const name = getViewTransitionName(props, state);
874789
const className: ?string = getViewTransitionClassName(
875790
props.className,
876-
props.layout,
791+
props.update,
877792
);
878793
let previousMeasurements: null | Array<InstanceMeasurement>;
879794
if (gesture) {
@@ -902,7 +817,7 @@ export function measureNestedViewTransitions(
902817
if (gesture) {
903818
// TODO: Schedule gesture events.
904819
} else {
905-
scheduleViewTransitionEvent(child, props.onLayout);
820+
scheduleViewTransitionEvent(child, props.onUpdate);
906821
}
907822
}
908823
} else if ((child.subtreeFlags & ViewTransitionStatic) !== NoFlags) {

packages/react-reconciler/src/ReactFiberCommitWork.js

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2440,8 +2440,6 @@ function commitAfterMutationEffectsOnFiber(
24402440
break;
24412441
}
24422442
case ViewTransitionComponent: {
2443-
const wasMutated = (finishedWork.flags & Update) !== NoFlags;
2444-
24452443
const prevContextChanged = viewTransitionContextChanged;
24462444
const prevCancelableChildren = pushViewTransitionCancelableScope();
24472445
viewTransitionContextChanged = false;
@@ -2477,12 +2475,7 @@ function commitAfterMutationEffectsOnFiber(
24772475
// then we should probably issue an event since this instance is part of it.
24782476
} else {
24792477
const props: ViewTransitionProps = finishedWork.memoizedProps;
2480-
scheduleViewTransitionEvent(
2481-
finishedWork,
2482-
wasMutated || viewTransitionContextChanged
2483-
? props.onUpdate
2484-
: props.onLayout,
2485-
);
2478+
scheduleViewTransitionEvent(finishedWork, props.onUpdate);
24862479

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

packages/react-reconciler/src/ReactFiberViewTransitionComponent.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,10 @@ export type ViewTransitionProps = {
3232
className?: ViewTransitionClass,
3333
enter?: ViewTransitionClass,
3434
exit?: ViewTransitionClass,
35-
layout?: ViewTransitionClass,
3635
share?: ViewTransitionClass,
3736
update?: ViewTransitionClass,
3837
onEnter?: (instance: ViewTransitionInstance, types: Array<string>) => void,
3938
onExit?: (instance: ViewTransitionInstance, types: Array<string>) => void,
40-
onLayout?: (instance: ViewTransitionInstance, types: Array<string>) => void,
4139
onShare?: (instance: ViewTransitionInstance, types: Array<string>) => void,
4240
onUpdate?: (instance: ViewTransitionInstance, types: Array<string>) => void,
4341
};

0 commit comments

Comments
 (0)