From 7b1d3667d90a2accc58f0b311c3d85a3610ddc78 Mon Sep 17 00:00:00 2001 From: Sebastian Markbage Date: Thu, 1 May 2025 18:24:16 -0400 Subject: [PATCH] Remove useId semantics from View Transition name generation --- .../src/ReactFiberBeginWork.js | 13 ------ .../src/ReactFiberViewTransitionComponent.js | 44 +++++-------------- .../src/ReactFiberWorkLoop.js | 4 ++ packages/react-server/src/ReactFizzServer.js | 18 +------- 4 files changed, 15 insertions(+), 64 deletions(-) diff --git a/packages/react-reconciler/src/ReactFiberBeginWork.js b/packages/react-reconciler/src/ReactFiberBeginWork.js index 4b9e7dee25119..975313a99f8b1 100644 --- a/packages/react-reconciler/src/ReactFiberBeginWork.js +++ b/packages/react-reconciler/src/ReactFiberBeginWork.js @@ -36,8 +36,6 @@ import type { OffscreenQueue, OffscreenInstance, } from './ReactFiberOffscreenComponent'; -import type {ViewTransitionState} from './ReactFiberViewTransitionComponent'; -import {assignViewTransitionAutoName} from './ReactFiberViewTransitionComponent'; import type { Cache, CacheComponentState, @@ -3538,7 +3536,6 @@ function updateViewTransition( renderLanes: Lanes, ) { const pendingProps: ViewTransitionProps = workInProgress.pendingProps; - const instance: ViewTransitionState = workInProgress.stateNode; if (pendingProps.name != null && pendingProps.name !== 'auto') { // Explicitly named boundary. We track it so that we can pair it up with another explicit // boundary if we get deleted. @@ -3546,16 +3543,6 @@ function updateViewTransition( current === null ? ViewTransitionNamedMount | ViewTransitionNamedStatic : ViewTransitionNamedStatic; - } else { - // Assign an auto generated name using the useId algorthim if an explicit one is not provided. - // We don't need the name yet but we do it here to allow hydration state to be used. - // We might end up needing these to line up if we want to Transition from dehydrated fallback - // to client rendered content. If we don't end up using that we could just assign an incremeting - // counter in the commit phase instead. - assignViewTransitionAutoName(pendingProps, instance); - if (getIsHydrating()) { - pushMaterializedTreeId(workInProgress); - } } if (__DEV__) { // $FlowFixMe[prop-missing] diff --git a/packages/react-reconciler/src/ReactFiberViewTransitionComponent.js b/packages/react-reconciler/src/ReactFiberViewTransitionComponent.js index eda56b0cc13e7..cda13a174a3aa 100644 --- a/packages/react-reconciler/src/ReactFiberViewTransitionComponent.js +++ b/packages/react-reconciler/src/ReactFiberViewTransitionComponent.js @@ -12,14 +12,10 @@ import type {FiberRoot} from './ReactInternalTypes'; import type {ViewTransitionInstance, Instance} from './ReactFiberConfig'; import { - getWorkInProgressRoot, + getCommittingRoot, getPendingTransitionTypes, } from './ReactFiberWorkLoop'; -import {getIsHydrating} from './ReactFiberHydrationContext'; - -import {getTreeId} from './ReactFiberTreeContext'; - export type ViewTransitionState = { autoName: null | string, // the view-transition-name to use when an explicit one is not specified paired: null | ViewTransitionState, // a temporary state during the commit phase if we have paired this with another instance @@ -29,47 +25,27 @@ export type ViewTransitionState = { let globalClientIdCounter: number = 0; -export function assignViewTransitionAutoName( +export function getViewTransitionName( props: ViewTransitionProps, instance: ViewTransitionState, ): string { + if (props.name != null && props.name !== 'auto') { + return props.name; + } if (instance.autoName !== null) { return instance.autoName; } - const root = ((getWorkInProgressRoot(): any): FiberRoot); + // We assume we always call this in the commit phase. + const root = ((getCommittingRoot(): any): FiberRoot); const identifierPrefix = root.identifierPrefix; - - let name; - if (getIsHydrating()) { - const treeId = getTreeId(); - // Use a captial R prefix for server-generated ids. - name = '\u00AB' + identifierPrefix + 'T' + treeId + '\u00BB'; - } else { - // Use a lowercase r prefix for client-generated ids. - const globalClientId = globalClientIdCounter++; - name = - '\u00AB' + - identifierPrefix + - 't' + - globalClientId.toString(32) + - '\u00BB'; - } + const globalClientId = globalClientIdCounter++; + const name = + '\u00AB' + identifierPrefix + 't' + globalClientId.toString(32) + '\u00BB'; instance.autoName = name; return name; } -export function getViewTransitionName( - props: ViewTransitionProps, - instance: ViewTransitionState, -): string { - if (props.name != null && props.name !== 'auto') { - return props.name; - } - // We should have assigned a name by now. - return (instance.autoName: any); -} - function getClassNameByType(classByType: ?ViewTransitionClass): ?string { if (classByType == null || typeof classByType === 'string') { return classByType; diff --git a/packages/react-reconciler/src/ReactFiberWorkLoop.js b/packages/react-reconciler/src/ReactFiberWorkLoop.js index f5b7bea38e6f8..a9924531103cb 100644 --- a/packages/react-reconciler/src/ReactFiberWorkLoop.js +++ b/packages/react-reconciler/src/ReactFiberWorkLoop.js @@ -699,6 +699,10 @@ export function getWorkInProgressRoot(): FiberRoot | null { return workInProgressRoot; } +export function getCommittingRoot(): FiberRoot | null { + return pendingEffectsRoot; +} + export function getWorkInProgressRootRenderLanes(): Lanes { return workInProgressRootRenderLanes; } diff --git a/packages/react-server/src/ReactFizzServer.js b/packages/react-server/src/ReactFizzServer.js index 65efe7c7e8935..72bb38c85b37f 100644 --- a/packages/react-server/src/ReactFizzServer.js +++ b/packages/react-server/src/ReactFizzServer.js @@ -2274,23 +2274,7 @@ function renderViewTransition( ) { const prevKeyPath = task.keyPath; task.keyPath = keyPath; - if (props.name != null && props.name !== 'auto') { - renderNodeDestructive(request, task, props.children, -1); - } else { - // This will be auto-assigned a name which claims a "useId" slot. - // This component materialized an id. We treat this as its own level, with - // a single "child" slot. - const prevTreeContext = task.treeContext; - const totalChildren = 1; - const index = 0; - // Modify the id context. Because we'll need to reset this if something - // suspends or errors, we'll use the non-destructive render path. - task.treeContext = pushTreeContext(prevTreeContext, totalChildren, index); - renderNode(request, task, props.children, -1); - // Like the other contexts, this does not need to be in a finally block - // because renderNode takes care of unwinding the stack. - task.treeContext = prevTreeContext; - } + renderNodeDestructive(request, task, props.children, -1); task.keyPath = prevKeyPath; }