diff --git a/fixtures/view-transition/src/components/Page.js b/fixtures/view-transition/src/components/Page.js index fbaa9017171..6227e9ebc5f 100644 --- a/fixtures/view-transition/src/components/Page.js +++ b/fixtures/view-transition/src/components/Page.js @@ -171,17 +171,20 @@ export default function Page({url, navigate}) { }}>

{!show ? 'A' + counter : 'B'}

- {show ? ( -
- {a} - {b} -
- ) : ( -
- {b} - {a} -
- )} + { + // Using url instead of renderedUrl here lets us only update this on commit. + url === '/?b' ? ( +
+ {a} + {b} +
+ ) : ( +
+ {b} + {a} +
+ ) + } {show ? (
hello{exclamation}
diff --git a/packages/react-reconciler/src/ReactFiberCommitViewTransitions.js b/packages/react-reconciler/src/ReactFiberCommitViewTransitions.js index 20abaa673c2..64940c31957 100644 --- a/packages/react-reconciler/src/ReactFiberCommitViewTransitions.js +++ b/packages/react-reconciler/src/ReactFiberCommitViewTransitions.js @@ -711,7 +711,11 @@ function measureViewTransitionHostInstancesRecursive( } viewTransitionCancelableChildren.push( instance, - oldName, + viewTransitionHostInstanceIdx === 0 + ? oldName + : // If we have multiple Host Instances below, we add a suffix to the name to give + // each one a unique name. + oldName + '_' + viewTransitionHostInstanceIdx, child.memoizedProps, ); } diff --git a/packages/react-reconciler/src/ReactFiberGestureScheduler.js b/packages/react-reconciler/src/ReactFiberGestureScheduler.js index ed61c59b05a..144d5f3aa5f 100644 --- a/packages/react-reconciler/src/ReactFiberGestureScheduler.js +++ b/packages/react-reconciler/src/ReactFiberGestureScheduler.js @@ -11,14 +11,21 @@ import type {FiberRoot} from './ReactInternalTypes'; import type {GestureOptions} from 'shared/ReactTypes'; import type {GestureTimeline, RunningViewTransition} from './ReactFiberConfig'; import type {TransitionTypes} from 'react/src/ReactTransitionType'; +import type {Lane} from './ReactFiberLane'; import { GestureLane, - includesBlockingLane, - includesTransitionLane, + markRootEntangled, + markRootFinished, + NoLane, + NoLanes, } from './ReactFiberLane'; -import {ensureRootIsScheduled} from './ReactFiberRootScheduler'; +import { + ensureRootIsScheduled, + requestTransitionLane, +} from './ReactFiberRootScheduler'; import {getCurrentGestureOffset, stopViewTransition} from './ReactFiberConfig'; +import {pingGestureRoot, restartGestureRoot} from './ReactFiberWorkLoop'; // This type keeps track of any scheduled or active gestures. export type ScheduledGesture = { @@ -28,6 +35,8 @@ export type ScheduledGesture = { rangeEnd: number, // The percentage along the timeline where the "destination" state is reached. types: null | TransitionTypes, // Any addTransitionType call made during startGestureTransition. running: null | RunningViewTransition, // Used to cancel the running transition after we're done. + committing: boolean, // If the gesture was released in a committed state and should actually commit. + revertLane: Lane, // The Lane that we'll use to schedule the revert. prev: null | ScheduledGesture, // The previous scheduled gesture in the queue for this root. next: null | ScheduledGesture, // The next scheduled gesture in the queue for this root. }; @@ -55,6 +64,8 @@ export function scheduleGesture( rangeEnd: 100, // Uninitialized types: null, running: null, + committing: false, + revertLane: NoLane, // Starts uninitialized. prev: prev, next: null, }; @@ -120,79 +131,107 @@ export function cancelScheduledGesture( root: FiberRoot, gesture: ScheduledGesture, ): void { + // Entangle any Transitions started in this event with the revertLane of the gesture + // so that we commit them all together. + if (gesture.revertLane !== NoLane) { + const entangledLanes = gesture.revertLane | requestTransitionLane(null); + markRootEntangled(root, entangledLanes); + } + gesture.count--; if (gesture.count === 0) { - // Delete the scheduled gesture from the pending queue. - deleteScheduledGesture(root, gesture); + // If the end state is closer to the end than the beginning then we commit into the + // end state before reverting back (or applying a new Transition). + // Otherwise we just revert back and don't commit. + let shouldCommit: boolean; + const finalOffset = getCurrentGestureOffset(gesture.provider); + const rangeStart = gesture.rangeStart; + const rangeEnd = gesture.rangeEnd; + if (rangeStart < rangeEnd) { + shouldCommit = finalOffset > rangeStart + (rangeEnd - rangeStart) / 2; + } else { + shouldCommit = finalOffset < rangeEnd + (rangeStart - rangeEnd) / 2; + } // TODO: If we're currently rendering this gesture, we need to restart the render // on a different gesture or cancel the render.. // TODO: We might want to pause the View Transition at this point since you should // no longer be able to update the position of anything but it might be better to // just commit the gesture state. const runningTransition = gesture.running; - if (runningTransition !== null) { - const pendingLanesExcludingGestureLane = root.pendingLanes & ~GestureLane; - if ( - includesBlockingLane(pendingLanesExcludingGestureLane) || - includesTransitionLane(pendingLanesExcludingGestureLane) - ) { - // If we have pending work we schedule the gesture to be stopped at the next commit. - // This ensures that we don't snap back to the previous state until we have - // had a chance to commit any resulting updates. - const existing = root.stoppingGestures; - if (existing !== null) { - gesture.next = existing; - existing.prev = gesture; + if (runningTransition !== null && shouldCommit) { + // If we are going to commit this gesture in its to state, we need to wait to + // stop it until it commits. We should now schedule a render at the gesture + // lane to actually commit it. + gesture.committing = true; + if (root.pendingGestures === gesture) { + // Ping the root given the new state. This is similar to pingSuspendedRoot. + // This will either schedule the gesture lane to be committed possibly from its current state. + pingGestureRoot(root); + } + } else { + // If we're not going to commit this gesture we can stop the View Transition + // right away and delete the scheduled gesture from the pending queue. + if (gesture.prev === null) { + if (root.pendingGestures === gesture) { + // This was the currently rendering gesture. + root.pendingGestures = gesture.next; + let remainingLanes = root.pendingLanes; + if (root.pendingGestures === null) { + // Gestures don't clear their lanes while the gesture is still active but it + // might not be scheduled to do any more renders and so we shouldn't schedule + // any more gesture lane work until a new gesture is scheduled. + remainingLanes &= ~GestureLane; + } + markRootFinished( + root, + GestureLane, + remainingLanes, + NoLane, + NoLane, + NoLanes, + ); + // If we had a currently rendering gesture we need to now reset the gesture lane to + // now render the next gesture or cancel if there's no more gestures in the queue. + restartGestureRoot(root); } - root.stoppingGestures = gesture; - } else { gesture.running = null; - // If there's no work scheduled so we can stop the View Transition right away. - stopViewTransition(runningTransition); + if (runningTransition !== null) { + stopViewTransition(runningTransition); + } + } else { + // This was not the current gesture so it doesn't affect the current render. + gesture.prev.next = gesture.next; + if (gesture.next !== null) { + gesture.next.prev = gesture.prev; + } + gesture.prev = null; + gesture.next = null; } } } } -export function deleteScheduledGesture( - root: FiberRoot, - gesture: ScheduledGesture, -): void { - if (gesture.prev === null) { - if (root.pendingGestures === gesture) { - root.pendingGestures = gesture.next; - if (root.pendingGestures === null) { - // Gestures don't clear their lanes while the gesture is still active but it - // might not be scheduled to do any more renders and so we shouldn't schedule - // any more gesture lane work until a new gesture is scheduled. - root.pendingLanes &= ~GestureLane; - } - } - if (root.stoppingGestures === gesture) { - // This should not really happen the way we use it now but just in case we start. - root.stoppingGestures = gesture.next; +export function stopCommittedGesture(root: FiberRoot) { + // The top was just committed. We can delete it from the queue + // and stop its View Transition now. + const committedGesture = root.pendingGestures; + if (committedGesture !== null) { + // Mark it as no longer committing and should no longer be included in rerenders. + committedGesture.committing = false; + const nextGesture = committedGesture.next; + if (nextGesture === null) { + // Gestures don't clear their lanes while the gesture is still active but it + // might not be scheduled to do any more renders and so we shouldn't schedule + // any more gesture lane work until a new gesture is scheduled. + root.pendingLanes &= ~GestureLane; + } else { + nextGesture.prev = null; } - } else { - gesture.prev.next = gesture.next; - if (gesture.next !== null) { - gesture.next.prev = gesture.prev; - } - gesture.prev = null; - gesture.next = null; - } -} - -export function stopCompletedGestures(root: FiberRoot) { - let gesture = root.stoppingGestures; - root.stoppingGestures = null; - while (gesture !== null) { - if (gesture.running !== null) { - stopViewTransition(gesture.running); - gesture.running = null; + root.pendingGestures = nextGesture; + const runningTransition = committedGesture.running; + if (runningTransition !== null) { + committedGesture.running = null; + stopViewTransition(runningTransition); } - const nextGesture = gesture.next; - gesture.next = null; - gesture.prev = null; - gesture = nextGesture; } } diff --git a/packages/react-reconciler/src/ReactFiberHooks.js b/packages/react-reconciler/src/ReactFiberHooks.js index 66a390ebb81..422667c6a12 100644 --- a/packages/react-reconciler/src/ReactFiberHooks.js +++ b/packages/react-reconciler/src/ReactFiberHooks.js @@ -1384,7 +1384,7 @@ function updateReducerImpl( // ScheduledGesture. const scheduledGesture = update.gesture; if (scheduledGesture !== null) { - if (scheduledGesture.count === 0) { + if (scheduledGesture.count === 0 && !scheduledGesture.committing) { // This gesture has already been cancelled. We can clean up this update. update = update.next; continue; @@ -3792,7 +3792,14 @@ function dispatchOptimisticSetState( if (provider !== null) { // If this was a gesture, ensure we have a scheduled gesture and that // we associate this update with this specific gesture instance. - update.gesture = scheduleGesture(root, provider); + const gesture = (update.gesture = scheduleGesture(root, provider)); + // Ensure the gesture always uses the same revert lane. This can happen for + // two startGestureTransition calls to the same provider in different events. + if (gesture.revertLane === NoLane) { + gesture.revertLane = update.revertLane; + } else { + update.revertLane = gesture.revertLane; + } } } } diff --git a/packages/react-reconciler/src/ReactFiberRoot.js b/packages/react-reconciler/src/ReactFiberRoot.js index 908893db948..26386597ee4 100644 --- a/packages/react-reconciler/src/ReactFiberRoot.js +++ b/packages/react-reconciler/src/ReactFiberRoot.js @@ -115,7 +115,6 @@ function FiberRootNode( if (enableGestureTransition) { this.pendingGestures = null; - this.stoppingGestures = null; this.gestureClone = null; } diff --git a/packages/react-reconciler/src/ReactFiberWorkLoop.js b/packages/react-reconciler/src/ReactFiberWorkLoop.js index f7200458be1..4fcf936f1cb 100644 --- a/packages/react-reconciler/src/ReactFiberWorkLoop.js +++ b/packages/react-reconciler/src/ReactFiberWorkLoop.js @@ -395,10 +395,7 @@ import { } from './ReactFiberRootScheduler'; import {getMaskedContext, getUnmaskedContext} from './ReactFiberLegacyContext'; import {logUncaughtError} from './ReactFiberErrorLogger'; -import { - deleteScheduledGesture, - stopCompletedGestures, -} from './ReactFiberGestureScheduler'; +import {stopCommittedGesture} from './ReactFiberGestureScheduler'; import {claimQueuedTransitionTypes} from './ReactFiberTransitionTypes'; const PossiblyWeakMap = typeof WeakMap === 'function' ? WeakMap : Map; @@ -1404,7 +1401,7 @@ function finishConcurrentRender( if (shouldForceFlushFallbacksInDEV()) { // We're inside an `act` scope. Commit immediately. - commitRoot( + completeRoot( root, finishedWork, lanes, @@ -1414,6 +1411,7 @@ function finishConcurrentRender( workInProgressDeferredLane, workInProgressRootInterleavedUpdatedLanes, workInProgressSuspendedRetryLanes, + workInProgressRootDidSkipSuspendedSiblings, exitStatus, null, null, @@ -1455,7 +1453,7 @@ function finishConcurrentRender( // run one after the other. pendingEffectsLanes = lanes; root.timeoutHandle = scheduleTimeout( - commitRootWhenReady.bind( + completeRootWhenReady.bind( null, root, finishedWork, @@ -1477,7 +1475,7 @@ function finishConcurrentRender( return; } } - commitRootWhenReady( + completeRootWhenReady( root, finishedWork, workInProgressRootRecoverableErrors, @@ -1496,7 +1494,7 @@ function finishConcurrentRender( } } -function commitRootWhenReady( +function completeRootWhenReady( root: FiberRoot, finishedWork: Fiber, recoverableErrors: Array> | null, @@ -1537,12 +1535,18 @@ function commitRootWhenReady( // This will also track any newly added or appearing ViewTransition // components for the purposes of forming pairs. accumulateSuspenseyCommit(finishedWork, lanes, suspendedState); - if (isViewTransitionEligible || isGestureTransition) { - // If we're stopping gestures we don't have to wait for any pending - // view transition. We'll stop it when we commit. - if (!enableGestureTransition || root.stoppingGestures === null) { - suspendOnActiveViewTransition(suspendedState, root.containerInfo); - } + if ( + isViewTransitionEligible || + (isGestureTransition && + root.pendingGestures !== null && + // If we're committing this gesture and it already has a View Transition + // running, then we don't have to wait for that gesture. We'll stop it + // when we commit. + (root.pendingGestures.running === null || + !root.pendingGestures.committing)) + ) { + // Wait for any pending View Transition (including gestures) to finish. + suspendOnActiveViewTransition(suspendedState, root.containerInfo); } // For timeouts we use the previous fallback commit for retries and // the start time of the transition for transitions. This offset @@ -1569,7 +1573,7 @@ function commitRootWhenReady( // root again. pendingEffectsLanes = lanes; root.cancelPendingCommit = schedulePendingCommit( - commitRoot.bind( + completeRoot.bind( null, root, finishedWork, @@ -1580,6 +1584,7 @@ function commitRootWhenReady( spawnedLane, updatedLanes, suspendedRetryLanes, + didSkipSuspendedSiblings, exitStatus, suspendedState, enableProfilerTimer @@ -1596,7 +1601,7 @@ function commitRootWhenReady( } // Otherwise, commit immediately.; - commitRoot( + completeRoot( root, finishedWork, lanes, @@ -1606,6 +1611,7 @@ function commitRootWhenReady( spawnedLane, updatedLanes, suspendedRetryLanes, + didSkipSuspendedSiblings, exitStatus, suspendedState, suspendedCommitReason, @@ -3413,7 +3419,7 @@ function unwindUnitOfWork(unitOfWork: Fiber, skipSiblings: boolean): void { workInProgress = null; } -function commitRoot( +function completeRoot( root: FiberRoot, finishedWork: null | Fiber, lanes: Lanes, @@ -3423,6 +3429,7 @@ function commitRoot( spawnedLane: Lane, updatedLanes: Lanes, suspendedRetryLanes: Lanes, + didSkipSuspendedSiblings: boolean, exitStatus: RootExitStatus, suspendedState: null | SuspendedState, suspendedCommitReason: SuspendedCommitReason, // Profiling-only @@ -3489,9 +3496,9 @@ function commitRoot( markCommitStopped(); } if (enableGestureTransition) { - // Stop any gestures that were completed and is now being reverted. - if (root.stoppingGestures !== null) { - stopCompletedGestures(root); + // Stop any gestures that were committed. + if (isGestureRender(lanes)) { + stopCommittedGesture(root); } } return; @@ -3513,10 +3520,95 @@ function commitRoot( ); } + if (root === workInProgressRoot) { + // We can reset these now that they are finished. + workInProgressRoot = null; + workInProgress = null; + workInProgressRootRenderLanes = NoLanes; + } else { + // This indicates that the last root we worked on is not the same one that + // we're committing now. This most commonly happens when a suspended root + // times out. + } + + // workInProgressX might be overwritten, so we want + // to store it in pendingPassiveX until they get processed + // We need to pass this through as an argument to completeRoot + // because workInProgressX might have changed between + // the previous render and commit if we throttle the commit + // with setTimeout + pendingFinishedWork = finishedWork; + pendingEffectsRoot = root; + pendingEffectsLanes = lanes; + pendingPassiveTransitions = transitions; + pendingRecoverableErrors = recoverableErrors; + pendingDidIncludeRenderPhaseUpdate = didIncludeRenderPhaseUpdate; + if (enableProfilerTimer) { + pendingEffectsRenderEndTime = completedRenderEndTime; + pendingSuspendedCommitReason = suspendedCommitReason; + pendingDelayedCommitReason = IMMEDIATE_COMMIT; + pendingSuspendedViewTransitionReason = null; + } + + if (enableGestureTransition && isGestureRender(lanes)) { + const committingGesture = root.pendingGestures; + if (committingGesture !== null && !committingGesture.committing) { + // This gesture is not ready to commit yet. We'll mark it as suspended and + // start a gesture transition which isn't really a side-effect. Then later + // we might come back around to actually committing the root. + const didAttemptEntireTree = !didSkipSuspendedSiblings; + markRootSuspended(root, lanes, spawnedLane, didAttemptEntireTree); + if (committingGesture.running === null) { + applyGestureOnRoot( + root, + finishedWork, + recoverableErrors, + suspendedState, + enableProfilerTimer + ? suspendedCommitReason === null + ? completedRenderEndTime + : commitStartTime + : 0, + ); + } else { + // If we already have a gesture running, we don't update it in place + // even if we have a new tree. Instead we wait until we can commit. + } + return; + } + } + + // If we're not starting a gesture we now actually commit the root. + commitRoot( + root, + finishedWork, + lanes, + spawnedLane, + updatedLanes, + suspendedRetryLanes, + suspendedState, + suspendedCommitReason, + completedRenderEndTime, + ); +} + +function commitRoot( + root: FiberRoot, + finishedWork: Fiber, + lanes: Lanes, + spawnedLane: Lane, + updatedLanes: Lanes, + suspendedRetryLanes: Lanes, + suspendedState: null | SuspendedState, + suspendedCommitReason: SuspendedCommitReason, // Profiling-only + completedRenderEndTime: number, // Profiling-only +) { // Check which lanes no longer have any work scheduled on them, and mark // those as finished. let remainingLanes = mergeLanes(finishedWork.lanes, finishedWork.childLanes); + pendingEffectsRemainingLanes = remainingLanes; + // Make sure to account for lanes that were updated by a concurrent event // during the render phase; don't mark them as finished. const concurrentlyUpdatedLanes = getConcurrentlyUpdatedLanes(); @@ -3546,53 +3638,6 @@ function commitRoot( // Reset this before firing side effects so we can detect recursive updates. didIncludeCommitPhaseUpdate = false; - if (root === workInProgressRoot) { - // We can reset these now that they are finished. - workInProgressRoot = null; - workInProgress = null; - workInProgressRootRenderLanes = NoLanes; - } else { - // This indicates that the last root we worked on is not the same one that - // we're committing now. This most commonly happens when a suspended root - // times out. - } - - // workInProgressX might be overwritten, so we want - // to store it in pendingPassiveX until they get processed - // We need to pass this through as an argument to commitRoot - // because workInProgressX might have changed between - // the previous render and commit if we throttle the commit - // with setTimeout - pendingFinishedWork = finishedWork; - pendingEffectsRoot = root; - pendingEffectsLanes = lanes; - pendingEffectsRemainingLanes = remainingLanes; - pendingPassiveTransitions = transitions; - pendingRecoverableErrors = recoverableErrors; - pendingDidIncludeRenderPhaseUpdate = didIncludeRenderPhaseUpdate; - if (enableProfilerTimer) { - pendingEffectsRenderEndTime = completedRenderEndTime; - pendingSuspendedCommitReason = suspendedCommitReason; - pendingDelayedCommitReason = IMMEDIATE_COMMIT; - pendingSuspendedViewTransitionReason = null; - } - - if (enableGestureTransition && isGestureRender(lanes)) { - // This is a special kind of render that doesn't commit regular effects. - commitGestureOnRoot( - root, - finishedWork, - recoverableErrors, - suspendedState, - enableProfilerTimer - ? suspendedCommitReason === null - ? completedRenderEndTime - : commitStartTime - : 0, - ); - return; - } - // If there are pending passive effects, schedule a callback to process them. // Do this as early as possible, so it is queued before anything else that // might get scheduled in the commit phase. (See #16714.) @@ -3705,20 +3750,19 @@ function commitRoot( } } - let willStartViewTransition = shouldStartViewTransition; if (enableGestureTransition) { - // Stop any gestures that were completed and is now being committed. - if (root.stoppingGestures !== null) { - stopCompletedGestures(root); - // If we are in the process of stopping some gesture we shouldn't start - // a View Transition because that would start from the previous state to - // the next state. - willStartViewTransition = false; + // Stop any gestures that were committed. + if (isGestureRender(lanes)) { + stopCommittedGesture(root); + // Note that shouldStartViewTransition should always be false here because + // committing a gesture never starts a new View Transition itself since it's + // not a View Transition eligible lane. Only follow up Transition commits can + // cause animate. } } pendingEffectsStatus = PENDING_MUTATION_PHASE; - if (enableViewTransition && willStartViewTransition) { + if (enableViewTransition && shouldStartViewTransition) { if (enableProfilerTimer && enableComponentPerformanceTrack) { startAnimating(lanes); } @@ -4148,7 +4192,7 @@ function flushSpawnedWork(): void { flushPendingEffects(); } - // Always call this before exiting `commitRoot`, to ensure that any + // Always call this before exiting `completeRoot`, to ensure that any // additional work on this root is scheduled. ensureRootIsScheduled(root); @@ -4237,7 +4281,7 @@ function flushSpawnedWork(): void { } } -function commitGestureOnRoot( +function applyGestureOnRoot( root: FiberRoot, finishedWork: Fiber, recoverableErrors: null | Array>, @@ -4252,7 +4296,6 @@ function commitGestureOnRoot( ensureRootIsScheduled(root); return; } - deleteScheduledGesture(root, finishedGesture); if (enableProfilerTimer && enableComponentPerformanceTrack) { startAnimating(pendingEffectsLanes); @@ -4461,7 +4504,7 @@ function flushPassiveEffects(): boolean { // flushPassiveEffectsImpl const root = pendingEffectsRoot; // Cache and clear the remaining lanes flag; it must be reset since this - // method can be called from various places, not always from commitRoot + // method can be called from various places, not always from completeRoot // where the remaining lanes are known const remainingLanes = pendingEffectsRemainingLanes; pendingEffectsRemainingLanes = NoLanes; @@ -4849,6 +4892,57 @@ function pingSuspendedRoot( ensureRootIsScheduled(root); } +export function pingGestureRoot(root: FiberRoot): void { + const gesture = root.pendingGestures; + if (gesture === null) { + return; + } + if ( + root.cancelPendingCommit !== null && + isGestureRender(pendingEffectsLanes) + ) { + // We have a suspended commit which we'll discard and rerender. + // TODO: Just use this commit since it's ready to go. + const cancelPendingCommit = root.cancelPendingCommit; + if (cancelPendingCommit !== null) { + root.cancelPendingCommit = null; + cancelPendingCommit(); + } + } + // Ping it for rerender and commit. + markRootPinged(root, GestureLane); + ensureRootIsScheduled(root); +} + +export function restartGestureRoot(root: FiberRoot): void { + if ( + workInProgressRoot === root && + isGestureRender(workInProgressRootRenderLanes) + ) { + // The current render was a gesture but it's now defunct. We need to restart the render. + if ((executionContext & RenderContext) === NoContext) { + prepareFreshStack(root, NoLanes); + } else { + // TODO: Throw interruption when supported again. + } + } else if ( + root.cancelPendingCommit !== null && + isGestureRender(pendingEffectsLanes) + ) { + // We have a suspended commit which we'll discard. + const cancelPendingCommit = root.cancelPendingCommit; + if (cancelPendingCommit !== null) { + root.cancelPendingCommit = null; + cancelPendingCommit(); + } + } + if (root.pendingGestures !== null) { + // We still have gestures to work on. Let's schedule a restart. + markRootPinged(root, GestureLane); + } + ensureRootIsScheduled(root); +} + function retryTimedOutBoundary(boundaryFiber: Fiber, retryLane: Lane) { // The boundary fiber (a Suspense component or SuspenseList component) // previously was rendered in its fallback state. One of the promises that diff --git a/packages/react-reconciler/src/ReactInternalTypes.js b/packages/react-reconciler/src/ReactInternalTypes.js index 775b69d211f..ce22050123c 100644 --- a/packages/react-reconciler/src/ReactInternalTypes.js +++ b/packages/react-reconciler/src/ReactInternalTypes.js @@ -292,7 +292,6 @@ type BaseFiberRootProperties = { transitionTypes: null | TransitionTypes, // TODO: Make this a LaneMap. // enableGestureTransition only pendingGestures: null | ScheduledGesture, - stoppingGestures: null | ScheduledGesture, gestureClone: null | Instance, };