Repository: facebook/react
Pull request: Disable strict effects for legacy roots (again)

See https://github.com/facebook/react/pull/21590#issuecomment-851556932 for context.

During the splitting of `<StrictMode>` into separate levels (#20849) the initial decision to disable strict effects for legacy roots was lost. This PR updates the mode assignment to be based on root mode as before. As of this PR, there are only two places we enable strict effects mode:

`createHostRootFiber()` if a strict flag is specified:
```js
export function createHostRootFiber(
  tag: RootTag,
  isStrictMode: boolean,
  concurrentUpdatesByDefaultOverride: null | boolean
): Fiber {
  let mode;
  if (tag === ConcurrentRoot) {
    mode = ConcurrentMode;
    if (isStrictMode === true) {
      mode |= StrictLegacyMode;

      if (enableStrictEffects) {
        mode |= StrictEffectsMode;
      }
    } else if (enableStrictEffects && createRootStrictEffectsByDefault) {
      mode |= StrictLegacyMode | StrictEffectsMode;
    }
```

`createFiberFromTypeAndProps()` if `<StrictMode>` is used within a modern root:
```js
mode |= StrictLegacyMode;
if (enableStrictEffects && (mode & ConcurrentMode) !== NoMode) {
  // Strict effects should never run on legacy roots
  mode |= StrictEffectsMode;
}
```

Changed files:
filename: packages/react-reconciler/src/ReactFiber.new.js
patch: @@ -492,7 +492,11 @@ export function createFiberFromTypeAndProps(
         break;
       case REACT_STRICT_MODE_TYPE:
         fiberTag = Mode;
-        mode |= StrictLegacyMode | StrictEffectsMode;
+        mode |= StrictLegacyMode;
+        if (enableStrictEffects && (mode & ConcurrentMode) !== NoMode) {
+          // Strict effects should never run on legacy roots
+          mode |= StrictEffectsMode;
+        }
         break;
       case REACT_PROFILER_TYPE:
         return createFiberFromProfiler(pendingProps, mode, lanes, key);

filename: packages/react-reconciler/src/ReactFiber.old.js
patch: @@ -492,7 +492,11 @@ export function createFiberFromTypeAndProps(
         break;
       case REACT_STRICT_MODE_TYPE:
         fiberTag = Mode;
-        mode |= StrictLegacyMode | StrictEffectsMode;
+        mode |= StrictLegacyMode;
+        if (enableStrictEffects && (mode & ConcurrentMode) !== NoMode) {
+          // Strict effects should never run on legacy roots
+          mode |= StrictEffectsMode;
+        }
         break;
       case REACT_PROFILER_TYPE:
         return createFiberFromProfiler(pendingProps, mode, lanes, key);

filename: packages/react-reconciler/src/ReactFiberClassComponent.new.js
patch: @@ -923,7 +923,6 @@ function mountClassInstance(
       enableStrictEffects &&
       (workInProgress.mode & StrictEffectsMode) !== NoMode
     ) {
-      // Never double-invoke effects for legacy roots.
       fiberFlags |= MountLayoutDev;
     }
     workInProgress.flags |= fiberFlags;
@@ -1005,7 +1004,6 @@ function resumeMountClassInstance(
         enableStrictEffects &&
         (workInProgress.mode & StrictEffectsMode) !== NoMode
       ) {
-        // Never double-invoke effects for legacy roots.
         fiberFlags |= MountLayoutDev;
       }
       workInProgress.flags |= fiberFlags;
@@ -1060,7 +1058,6 @@ function resumeMountClassInstance(
         enableStrictEffects &&
         (workInProgress.mode & StrictEffectsMode) !== NoMode
       ) {
-        // Never double-invoke effects for legacy roots.
         fiberFlags |= MountLayoutDev;
       }
       workInProgress.flags |= fiberFlags;
@@ -1078,7 +1075,6 @@ function resumeMountClassInstance(
         enableStrictEffects &&
         (workInProgress.mode & StrictEffectsMode) !== NoMode
       ) {
-        // Never double-invoke effects for legacy roots.
         fiberFlags |= MountLayoutDev;
       }
       workInProgress.flags |= fiberFlags;

filename: packages/react-reconciler/src/ReactFiberClassComponent.old.js
patch: @@ -923,7 +923,6 @@ function mountClassInstance(
       enableStrictEffects &&
       (workInProgress.mode & StrictEffectsMode) !== NoMode
     ) {
-      // Never double-invoke effects for legacy roots.
       fiberFlags |= MountLayoutDev;
     }
     workInProgress.flags |= fiberFlags;
@@ -1005,7 +1004,6 @@ function resumeMountClassInstance(
         enableStrictEffects &&
         (workInProgress.mode & StrictEffectsMode) !== NoMode
       ) {
-        // Never double-invoke effects for legacy roots.
         fiberFlags |= MountLayoutDev;
       }
       workInProgress.flags |= fiberFlags;
@@ -1060,7 +1058,6 @@ function resumeMountClassInstance(
         enableStrictEffects &&
         (workInProgress.mode & StrictEffectsMode) !== NoMode
       ) {
-        // Never double-invoke effects for legacy roots.
         fiberFlags |= MountLayoutDev;
       }
       workInProgress.flags |= fiberFlags;
@@ -1078,7 +1075,6 @@ function resumeMountClassInstance(
         enableStrictEffects &&
         (workInProgress.mode & StrictEffectsMode) !== NoMode
       ) {
-        // Never double-invoke effects for legacy roots.
         fiberFlags |= MountLayoutDev;
       }
       workInProgress.flags |= fiberFlags;