Repository: facebook/react
Pull request: Remove Gesture warning when cloning the root

Currently we always clone the root when a gesture transition happens. The was to add an optimization where if a Transition could be isolated to an absolutely positioned subtree then we could just clone that subtree or just do a plain insertion if it was simple an Enter. That way when switching between two absolutely positioned pages the shell wouldn't need to be cloned. In that case `detectMutationOrInsertClones` would return false. However, currently it always return true because we don't yet have that optimization.

The idea was to warn when the root required cloning to ensure that you optimize it intentionally since it's easy to accidentally update more than necessary. However, since this is not yet actionable I'm removing this warning for now.

Instead, I add a warning for particularly bad cases where you really shouldn't clone like iframe and video. They may not be very actionable without the optimization since you can't scope it down to a subtree without the optimization. So if they're above the gesture then they're always cloned atm. However, it might also be that it's unnecessary to keep them mounted if they could be removed or hidden with Activity.


Changed files:
filename: packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js
patch: @@ -607,10 +607,32 @@ export function createInstance(
   return domElement;
 }
 
+let didWarnForClone = false;
+
 export function cloneMutableInstance(
   instance: Instance,
   keepChildren: boolean,
 ): Instance {
+  if (__DEV__) {
+    // Warn for problematic
+    const tagName = instance.tagName;
+    switch (tagName) {
+      case 'VIDEO':
+      case 'IFRAME':
+        if (!didWarnForClone) {
+          didWarnForClone = true;
+          // TODO: Once we have the ability to avoid cloning the root, suggest an absolutely
+          // positioned ViewTransition instead as the solution.
+          console.warn(
+            'startGestureTransition() required cloning a <%s> element since it exists in ' +
+              'both states of the gesture. This can be problematic since it will load it twice ' +
+              'Try removing or hiding it with <Activity mode="offscreen"> in the optimistic state.',
+            tagName.toLowerCase(),
+          );
+        }
+        break;
+    }
+  }
   return instance.cloneNode(keepChildren);
 }
 

filename: packages/react-reconciler/src/ReactFiberApplyGesture.js
patch: @@ -97,8 +97,6 @@ import {
 import {trackAnimatingTask} from './ReactProfilerTimer';
 import {scheduleGestureTransitionEvent} from './ReactFiberWorkLoop';
 
-let didWarnForRootClone = false;
-
 // Used during the apply phase to track whether a parent ViewTransition component
 // might have been affected by any mutations / relayouts below.
 let viewTransitionContextChanged: boolean = false;
@@ -1033,17 +1031,6 @@ export function insertDestinationClones(
   // we cancel the root view transition name.
   const needsClone = detectMutationOrInsertClones(finishedWork);
   if (needsClone) {
-    if (__DEV__) {
-      if (!didWarnForRootClone) {
-        didWarnForRootClone = true;
-        console.warn(
-          'startGestureTransition() caused something to mutate or relayout the root. ' +
-            'This currently requires a clone of the whole document. Make sure to ' +
-            'add a <ViewTransition> directly around an absolutely positioned DOM node ' +
-            'to minimize the impact of any changes caused by the Gesture Transition.',
-        );
-      }
-    }
     // Clone the whole root
     const rootClone = cloneRootViewTransitionContainer(root.containerInfo);
     root.gestureClone = rootClone;