Skip to content

Add component names to ViewTransition autoName in DEV #33092

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
22 changes: 13 additions & 9 deletions fixtures/view-transition/src/components/Page.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,15 +96,7 @@ export default function Page({url, navigate}) {

const [showModal, setShowModal] = useState(false);
const portal = showModal ? (
createPortal(
<div className="portal">
Portal: {!show ? 'A' : 'B'}
<ViewTransition>
<div>{!show ? 'A' : 'B'}</div>
</ViewTransition>
</div>,
document.body
)
createPortal(<Modal show={show} />, document.body)
) : (
<button onClick={() => startTransition(() => setShowModal(true))}>
Show Modal
Expand Down Expand Up @@ -202,3 +194,15 @@ export default function Page({url, navigate}) {
</div>
);
}

const Modal = function ({show}) {
return (
<div className="portal">
Portal: {!show ? 'A' : 'B'}
<ViewTransition>
<div>{!show ? 'A' : 'B'}</div>
</ViewTransition>
</div>
);
};
Modal.displayName = '#ModalName@InvalidCharacters#';
13 changes: 6 additions & 7 deletions packages/react-reconciler/src/ReactFiberApplyGesture.js
Original file line number Diff line number Diff line change
Expand Up @@ -188,12 +188,12 @@ function trackDeletedPairViewTransitions(deletion: Fiber): void {

function trackEnterViewTransitions(deletion: Fiber): void {
if (deletion.tag === ViewTransitionComponent) {
const props: ViewTransitionProps = deletion.memoizedProps;
const name = getViewTransitionName(props, deletion.stateNode);
const name = getViewTransitionName(deletion);
const pair =
appearingViewTransitions !== null
? appearingViewTransitions.get(name)
: undefined;
const props: ViewTransitionProps = deletion.memoizedProps;
const className: ?string = getViewTransitionClassName(
props.default,
pair !== undefined ? props.share : props.enter,
Expand Down Expand Up @@ -277,9 +277,9 @@ function applyExitViewTransition(placement: Fiber): void {
// Normally these helpers do recursive calls but since insertion/offscreen is forked
// we call this helper from those loops instead. This must be called only on
// ViewTransitionComponent that has already had their clones filled.
const name = getViewTransitionName(placement);
const state: ViewTransitionState = placement.stateNode;
const props: ViewTransitionProps = placement.memoizedProps;
const name = getViewTransitionName(props, state);
const className: ?string = getViewTransitionClassName(
props.default,
// Note that just because we don't have a pair yet doesn't mean we won't find one
Expand All @@ -302,9 +302,9 @@ function applyExitViewTransition(placement: Fiber): void {
}

function applyNestedViewTransition(child: Fiber): void {
const name = getViewTransitionName(child);
const state: ViewTransitionState = child.stateNode;
const props: ViewTransitionProps = child.memoizedProps;
const name = getViewTransitionName(props, state);
const className: ?string = getViewTransitionClassName(
props.default,
props.update,
Expand All @@ -324,16 +324,15 @@ function applyUpdateViewTransition(current: Fiber, finishedWork: Fiber): void {
// Updates can have conflicting names and classNames.
// Since we're doing a reverse animation the "new" state is actually the current
// and the "old" state is the finishedWork.
const newProps: ViewTransitionProps = current.memoizedProps;
const oldProps: ViewTransitionProps = finishedWork.memoizedProps;
const oldName = getViewTransitionName(oldProps, state);
const oldName = getViewTransitionName(finishedWork);
// This className applies only if there are fewer child DOM nodes than
// before or if this update should've been cancelled but we ended up with
// a parent animating so we need to animate the child too. Otherwise
// the "new" state wins. Since "new" normally wins, that's usually what
// we would use. However, since this animation is going in reverse we actually
// want the props from "current" since that's the class that would've won if
// it was the normal direction. To preserve the same effect in either direction.
const newProps: ViewTransitionProps = current.memoizedProps;
const className: ?string = getViewTransitionClassName(
newProps.default,
newProps.update,
Expand Down
9 changes: 2 additions & 7 deletions packages/react-reconciler/src/ReactFiberCommitEffects.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,7 @@
* @flow
*/

import type {
ViewTransitionProps,
ProfilerProps,
ProfilerPhase,
} from 'shared/ReactTypes';
import type {ProfilerProps, ProfilerPhase} from 'shared/ReactTypes';
import type {Fiber} from './ReactInternalTypes';
import type {UpdateQueue} from './ReactFiberClassUpdateQueue';
import type {FunctionComponentUpdateQueue} from './ReactFiberHooks';
Expand Down Expand Up @@ -768,9 +764,8 @@ function commitAttachRef(finishedWork: Fiber) {
break;
case ViewTransitionComponent: {
if (enableViewTransition) {
const name = getViewTransitionName(finishedWork);
const instance: ViewTransitionState = finishedWork.stateNode;
const props: ViewTransitionProps = finishedWork.memoizedProps;
const name = getViewTransitionName(props, instance);
if (instance.ref === null || instance.ref.name !== name) {
instance.ref = createViewTransitionInstance(name);
}
Expand Down
19 changes: 9 additions & 10 deletions packages/react-reconciler/src/ReactFiberCommitViewTransitions.js
Original file line number Diff line number Diff line change
Expand Up @@ -275,9 +275,9 @@ export function commitEnterViewTransitions(
gesture: boolean,
): void {
if (placement.tag === ViewTransitionComponent) {
const name = getViewTransitionName(placement);
const state: ViewTransitionState = placement.stateNode;
const props: ViewTransitionProps = placement.memoizedProps;
const name = getViewTransitionName(props, state);
const className: ?string = getViewTransitionClassName(
props.default,
state.paired ? props.share : props.enter,
Expand Down Expand Up @@ -394,12 +394,12 @@ function commitDeletedPairViewTransitions(deletion: Fiber): void {

export function commitExitViewTransitions(deletion: Fiber): void {
if (deletion.tag === ViewTransitionComponent) {
const props: ViewTransitionProps = deletion.memoizedProps;
const name = getViewTransitionName(props, deletion.stateNode);
const name = getViewTransitionName(deletion);
const pair =
appearingViewTransitions !== null
? appearingViewTransitions.get(name)
: undefined;
const props: ViewTransitionProps = deletion.memoizedProps;
const className: ?string = getViewTransitionClassName(
props.default,
pair !== undefined ? props.share : props.exit,
Expand Down Expand Up @@ -472,8 +472,7 @@ export function commitBeforeUpdateViewTransition(
// be unexpected but it is in line with the semantics that the ViewTransition is its
// own layer that cross-fades its content when it updates. If you want to reorder then
// each child needs its own ViewTransition.
const oldProps: ViewTransitionProps = current.memoizedProps;
const oldName = getViewTransitionName(oldProps, current.stateNode);
const oldName = getViewTransitionName(current);
const newProps: ViewTransitionProps = finishedWork.memoizedProps;
// This className applies only if there are fewer child DOM nodes than
// before or if this update should've been cancelled but we ended up with
Expand Down Expand Up @@ -504,8 +503,8 @@ export function commitNestedViewTransitions(changedParent: Fiber): void {
if (child.tag === ViewTransitionComponent) {
// In this case the outer ViewTransition component wins but if there
// was an update through this component then the inner one wins.
const name = getViewTransitionName(child);
const props: ViewTransitionProps = child.memoizedProps;
const name = getViewTransitionName(props, child.stateNode);
const className: ?string = getViewTransitionClassName(
props.default,
props.update,
Expand Down Expand Up @@ -747,11 +746,11 @@ export function measureUpdateViewTransition(
// We still need to treat "finishedWork" as the Fiber that contains the flags for this commmit.
const oldFiber = gesture ? finishedWork : current;
const newFiber = gesture ? current : finishedWork;
const newName = getViewTransitionName(newFiber);
const oldName = getViewTransitionName(oldFiber);
// Whether it ends up having been updated or relayout we apply the update class name.
const props: ViewTransitionProps = newFiber.memoizedProps;
const state: ViewTransitionState = newFiber.stateNode;
const newName = getViewTransitionName(props, state);
const oldName = getViewTransitionName(oldFiber.memoizedProps, state);
// Whether it ends up having been updated or relayout we apply the update class name.
const className: ?string = getViewTransitionClassName(
props.default,
props.update,
Expand Down Expand Up @@ -801,9 +800,9 @@ export function measureNestedViewTransitions(
let child = changedParent.child;
while (child !== null) {
if (child.tag === ViewTransitionComponent) {
const name = getViewTransitionName(child);
const props: ViewTransitionProps = child.memoizedProps;
const state: ViewTransitionState = child.stateNode;
const name = getViewTransitionName(props, state);
const className: ?string = getViewTransitionClassName(
props.default,
props.update,
Expand Down
52 changes: 45 additions & 7 deletions packages/react-reconciler/src/ReactFiberViewTransitionComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@
*/

import type {ViewTransitionClass, ViewTransitionProps} from 'shared/ReactTypes';
import type {FiberRoot} from './ReactInternalTypes';
import type {Fiber, FiberRoot} from './ReactInternalTypes';
import type {ViewTransitionInstance, Instance} from './ReactFiberConfig';

import {
getCommittingRoot,
getPendingTransitionTypes,
} from './ReactFiberWorkLoop';
import {getComponentNameFromOwner} from './getComponentNameFromFiber';

export type ViewTransitionState = {
autoName: null | string, // the view-transition-name to use when an explicit one is not specified
Expand All @@ -25,10 +26,10 @@ export type ViewTransitionState = {

let globalClientIdCounter: number = 0;

export function getViewTransitionName(
props: ViewTransitionProps,
instance: ViewTransitionState,
): string {
export function getViewTransitionName(viewTransitionFiber: Fiber): string {
const props: ViewTransitionProps = viewTransitionFiber.memoizedProps;
const instance: ViewTransitionState = viewTransitionFiber.stateNode;

if (props.name != null && props.name !== 'auto') {
return props.name;
}
Expand All @@ -40,12 +41,49 @@ export function getViewTransitionName(
const root = ((getCommittingRoot(): any): FiberRoot);
const identifierPrefix = root.identifierPrefix;
const globalClientId = globalClientIdCounter++;
const name =
'\u00AB' + identifierPrefix + 't' + globalClientId.toString(32) + '\u00BB';
let name = '';
if (__DEV__) {
let owner = '';
if (viewTransitionFiber._debugOwner) {
const componentName = getComponentNameFromOwner(
viewTransitionFiber._debugOwner,
);
if (componentName) {
owner = formatOwnerNameDEV(componentName);
} else {
owner = 'UnnamedOwner';
}
} else {
owner = 'UnknownOwner';
}
name =
'\u00AB' +
identifierPrefix +
't' +
globalClientId.toString(32) +
'_' +
owner +
'_' +
'\u00BB';
} else {
name =
'\u00AB' +
identifierPrefix +
't' +
globalClientId.toString(32) +
'\u00BB';
}
instance.autoName = name;
return name;
}

function formatOwnerNameDEV(ownerName: string): string {
// Strip to 16 characters and replace invalid characters.
// We don't need to replace invalid first characters or forbidden values
// because result will be prefixed.
return ownerName.slice(0, 16).replace(/[^a-zA-Z0-9_-]/g, '\u2733');
}

function getClassNameByType(classByType: ?ViewTransitionClass): ?string {
if (classByType == null || typeof classByType === 'string') {
return classByType;
Expand Down
2 changes: 1 addition & 1 deletion packages/react-reconciler/src/ReactFiberWorkLoop.js
Original file line number Diff line number Diff line change
Expand Up @@ -856,7 +856,7 @@ export function scheduleViewTransitionEvent(
let instance = state.ref;
if (instance === null) {
instance = state.ref = createViewTransitionInstance(
getViewTransitionName(fiber.memoizedProps, state),
getViewTransitionName(fiber),
);
}
if (pendingViewTransitionEvents === null) {
Expand Down
Loading