From b4e9696071bd6a610e9749911e5d9c7aa8001b7e Mon Sep 17 00:00:00 2001
From: Rick Hanlon <rickhanlonii@gmail.com>
Date: Tue, 4 May 2021 14:38:08 -0400
Subject: [PATCH 1/3] Add back root override for strict mode

---
 .../src/__tests__/ReactTestUtilsAct-test.js   | 14 ++++++++++++
 packages/react-dom/src/client/ReactDOMRoot.js |  4 ++++
 .../react-native-renderer/src/ReactFabric.js  |  2 +-
 .../src/ReactNativeRenderer.js                |  2 +-
 .../src/createReactNoop.js                    |  4 +++-
 .../react-reconciler/src/ReactFiber.new.js    | 12 +++++++++-
 .../react-reconciler/src/ReactFiber.old.js    | 12 +++++++++-
 .../src/ReactFiberReconciler.new.js           |  2 ++
 .../src/ReactFiberReconciler.old.js           |  2 ++
 .../src/ReactFiberRoot.new.js                 |  2 ++
 .../src/ReactFiberRoot.old.js                 |  2 ++
 .../src/ReactTestRenderer.js                  |  6 +++++
 .../ReactStrictMode-test.internal.js          | 22 +++++++++++++++++++
 13 files changed, 81 insertions(+), 5 deletions(-)

diff --git a/packages/react-dom/src/__tests__/ReactTestUtilsAct-test.js b/packages/react-dom/src/__tests__/ReactTestUtilsAct-test.js
index 8419c93c38c41..dee4b7852a837 100644
--- a/packages/react-dom/src/__tests__/ReactTestUtilsAct-test.js
+++ b/packages/react-dom/src/__tests__/ReactTestUtilsAct-test.js
@@ -102,6 +102,20 @@ describe('ReactTestUtils.act()', () => {
       root.render(<App />);
       Scheduler.unstable_flushAll();
     });
+
+    // @gate experimental
+    it('warns in concurrent mode if root is strict', () => {
+      expect(() => {
+        const root = ReactDOM.unstable_createRoot(
+          document.createElement('div'),
+          {unstable_strictMode: true},
+        );
+        root.render(<App />);
+        Scheduler.unstable_flushAll();
+      }).toErrorDev([
+        'An update to App ran an effect, but was not wrapped in act(...)',
+      ]);
+    });
   });
 });
 
diff --git a/packages/react-dom/src/client/ReactDOMRoot.js b/packages/react-dom/src/client/ReactDOMRoot.js
index 73e96eb086bbc..f99c092cfd8fe 100644
--- a/packages/react-dom/src/client/ReactDOMRoot.js
+++ b/packages/react-dom/src/client/ReactDOMRoot.js
@@ -27,6 +27,7 @@ export type RootOptions = {
     mutableSources?: Array<MutableSource<any>>,
     ...
   },
+  unstable_strictMode?: boolean,
   unstable_concurrentUpdatesByDefault?: boolean,
   ...
 };
@@ -122,6 +123,8 @@ function createRootImpl(
       options.hydrationOptions != null &&
       options.hydrationOptions.mutableSources) ||
     null;
+  const strictModeLevelOverride =
+    options != null && options.unstable_strictMode === true ? 2 : null;
 
   let concurrentUpdatesByDefaultOverride = null;
   if (allowConcurrentByDefault) {
@@ -136,6 +139,7 @@ function createRootImpl(
     tag,
     hydrate,
     hydrationCallbacks,
+    strictModeLevelOverride,
     concurrentUpdatesByDefaultOverride,
   );
   markContainerAsRoot(root.current, container);
diff --git a/packages/react-native-renderer/src/ReactFabric.js b/packages/react-native-renderer/src/ReactFabric.js
index 9f1f44f51cf49..b319cb22c7b7b 100644
--- a/packages/react-native-renderer/src/ReactFabric.js
+++ b/packages/react-native-renderer/src/ReactFabric.js
@@ -207,7 +207,7 @@ function render(
   if (!root) {
     // TODO (bvaughn): If we decide to keep the wrapper component,
     // We could create a wrapper for containerTag as well to reduce special casing.
-    root = createContainer(containerTag, LegacyRoot, false, null, null);
+    root = createContainer(containerTag, LegacyRoot, false, null, null, null);
     roots.set(containerTag, root);
   }
   updateContainer(element, root, null, callback);
diff --git a/packages/react-native-renderer/src/ReactNativeRenderer.js b/packages/react-native-renderer/src/ReactNativeRenderer.js
index de42c6e41a58c..4f73377320378 100644
--- a/packages/react-native-renderer/src/ReactNativeRenderer.js
+++ b/packages/react-native-renderer/src/ReactNativeRenderer.js
@@ -203,7 +203,7 @@ function render(
   if (!root) {
     // TODO (bvaughn): If we decide to keep the wrapper component,
     // We could create a wrapper for containerTag as well to reduce special casing.
-    root = createContainer(containerTag, LegacyRoot, false, null, null);
+    root = createContainer(containerTag, LegacyRoot, false, null, null, null);
     roots.set(containerTag, root);
   }
   updateContainer(element, root, null, callback);
diff --git a/packages/react-noop-renderer/src/createReactNoop.js b/packages/react-noop-renderer/src/createReactNoop.js
index 659f4d63fcc03..9d2c87621bcef 100644
--- a/packages/react-noop-renderer/src/createReactNoop.js
+++ b/packages/react-noop-renderer/src/createReactNoop.js
@@ -722,7 +722,7 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
       if (!root) {
         const container = {rootID: rootID, pendingChildren: [], children: []};
         rootContainers.set(rootID, container);
-        root = NoopRenderer.createContainer(container, tag, false, null);
+        root = NoopRenderer.createContainer(container, tag, false, null, null);
         roots.set(rootID, root);
       }
       return root.current.stateNode.containerInfo;
@@ -740,6 +740,7 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
         ConcurrentRoot,
         false,
         null,
+        null,
       );
       return {
         _Scheduler: Scheduler,
@@ -766,6 +767,7 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
         LegacyRoot,
         false,
         null,
+        null,
       );
       return {
         _Scheduler: Scheduler,
diff --git a/packages/react-reconciler/src/ReactFiber.new.js b/packages/react-reconciler/src/ReactFiber.new.js
index 13cbe26b5acc4..1b5afea0da661 100644
--- a/packages/react-reconciler/src/ReactFiber.new.js
+++ b/packages/react-reconciler/src/ReactFiber.new.js
@@ -422,12 +422,22 @@ export function resetWorkInProgress(workInProgress: Fiber, renderLanes: Lanes) {
 
 export function createHostRootFiber(
   tag: RootTag,
+  strictModeLevelOverride: null | number,
   concurrentUpdatesByDefaultOverride: null | boolean,
 ): Fiber {
   let mode;
   if (tag === ConcurrentRoot) {
     mode = ConcurrentMode;
-    if (enableStrictEffects && createRootStrictEffectsByDefault) {
+    if (strictModeLevelOverride !== null) {
+      if (strictModeLevelOverride >= 1) {
+        mode |= StrictLegacyMode;
+      }
+      if (enableStrictEffects) {
+        if (strictModeLevelOverride >= 2) {
+          mode |= StrictEffectsMode;
+        }
+      }
+    } else if (enableStrictEffects && createRootStrictEffectsByDefault) {
       mode |= StrictLegacyMode | StrictEffectsMode;
     }
     if (
diff --git a/packages/react-reconciler/src/ReactFiber.old.js b/packages/react-reconciler/src/ReactFiber.old.js
index 40a09820beae4..21e6affdd8a5a 100644
--- a/packages/react-reconciler/src/ReactFiber.old.js
+++ b/packages/react-reconciler/src/ReactFiber.old.js
@@ -422,12 +422,22 @@ export function resetWorkInProgress(workInProgress: Fiber, renderLanes: Lanes) {
 
 export function createHostRootFiber(
   tag: RootTag,
+  strictModeLevelOverride: null | number,
   concurrentUpdatesByDefaultOverride: null | boolean,
 ): Fiber {
   let mode;
   if (tag === ConcurrentRoot) {
     mode = ConcurrentMode;
-    if (enableStrictEffects && createRootStrictEffectsByDefault) {
+    if (strictModeLevelOverride !== null) {
+      if (strictModeLevelOverride >= 1) {
+        mode |= StrictLegacyMode;
+      }
+      if (enableStrictEffects) {
+        if (strictModeLevelOverride >= 2) {
+          mode |= StrictEffectsMode;
+        }
+      }
+    } else if (enableStrictEffects && createRootStrictEffectsByDefault) {
       mode |= StrictLegacyMode | StrictEffectsMode;
     }
     if (
diff --git a/packages/react-reconciler/src/ReactFiberReconciler.new.js b/packages/react-reconciler/src/ReactFiberReconciler.new.js
index b19223db377a4..f53a24e86c60b 100644
--- a/packages/react-reconciler/src/ReactFiberReconciler.new.js
+++ b/packages/react-reconciler/src/ReactFiberReconciler.new.js
@@ -248,6 +248,7 @@ export function createContainer(
   tag: RootTag,
   hydrate: boolean,
   hydrationCallbacks: null | SuspenseHydrationCallbacks,
+  strictModeLevelOverride: null | number,
   concurrentUpdatesByDefaultOverride: null | boolean,
 ): OpaqueRoot {
   return createFiberRoot(
@@ -255,6 +256,7 @@ export function createContainer(
     tag,
     hydrate,
     hydrationCallbacks,
+    strictModeLevelOverride,
     concurrentUpdatesByDefaultOverride,
   );
 }
diff --git a/packages/react-reconciler/src/ReactFiberReconciler.old.js b/packages/react-reconciler/src/ReactFiberReconciler.old.js
index fe528b8316c82..00c12b3406df8 100644
--- a/packages/react-reconciler/src/ReactFiberReconciler.old.js
+++ b/packages/react-reconciler/src/ReactFiberReconciler.old.js
@@ -248,6 +248,7 @@ export function createContainer(
   tag: RootTag,
   hydrate: boolean,
   hydrationCallbacks: null | SuspenseHydrationCallbacks,
+  strictModeLevelOverride: null | number,
   concurrentUpdatesByDefaultOverride: null | boolean,
 ): OpaqueRoot {
   return createFiberRoot(
@@ -255,6 +256,7 @@ export function createContainer(
     tag,
     hydrate,
     hydrationCallbacks,
+    strictModeLevelOverride,
     concurrentUpdatesByDefaultOverride,
   );
 }
diff --git a/packages/react-reconciler/src/ReactFiberRoot.new.js b/packages/react-reconciler/src/ReactFiberRoot.new.js
index ae62134de1bc1..d2efcc5851d49 100644
--- a/packages/react-reconciler/src/ReactFiberRoot.new.js
+++ b/packages/react-reconciler/src/ReactFiberRoot.new.js
@@ -98,6 +98,7 @@ export function createFiberRoot(
   tag: RootTag,
   hydrate: boolean,
   hydrationCallbacks: null | SuspenseHydrationCallbacks,
+  strictModeLevelOverride: null | number,
   concurrentUpdatesByDefaultOverride: null | boolean,
 ): FiberRoot {
   const root: FiberRoot = (new FiberRootNode(containerInfo, tag, hydrate): any);
@@ -109,6 +110,7 @@ export function createFiberRoot(
   // stateNode is any.
   const uninitializedFiber = createHostRootFiber(
     tag,
+    strictModeLevelOverride,
     concurrentUpdatesByDefaultOverride,
   );
   root.current = uninitializedFiber;
diff --git a/packages/react-reconciler/src/ReactFiberRoot.old.js b/packages/react-reconciler/src/ReactFiberRoot.old.js
index 83d4de95b6a8b..68d329492cf1b 100644
--- a/packages/react-reconciler/src/ReactFiberRoot.old.js
+++ b/packages/react-reconciler/src/ReactFiberRoot.old.js
@@ -98,6 +98,7 @@ export function createFiberRoot(
   tag: RootTag,
   hydrate: boolean,
   hydrationCallbacks: null | SuspenseHydrationCallbacks,
+  strictModeLevelOverride: null | number,
   concurrentUpdatesByDefaultOverride: null | boolean,
 ): FiberRoot {
   const root: FiberRoot = (new FiberRootNode(containerInfo, tag, hydrate): any);
@@ -109,6 +110,7 @@ export function createFiberRoot(
   // stateNode is any.
   const uninitializedFiber = createHostRootFiber(
     tag,
+    strictModeLevelOverride,
     concurrentUpdatesByDefaultOverride,
   );
   root.current = uninitializedFiber;
diff --git a/packages/react-test-renderer/src/ReactTestRenderer.js b/packages/react-test-renderer/src/ReactTestRenderer.js
index bc46f1d6d182f..aa44a8d118543 100644
--- a/packages/react-test-renderer/src/ReactTestRenderer.js
+++ b/packages/react-test-renderer/src/ReactTestRenderer.js
@@ -58,6 +58,7 @@ const {IsSomeRendererActing} = ReactSharedInternals;
 type TestRendererOptions = {
   createNodeMock: (element: React$Element<any>) => any,
   unstable_isConcurrent: boolean,
+  unstable_strictMode: boolean,
   unstable_concurrentUpdatesByDefault: boolean,
   ...
 };
@@ -436,6 +437,7 @@ function propsMatch(props: Object, filter: Object): boolean {
 function create(element: React$Element<any>, options: TestRendererOptions) {
   let createNodeMock = defaultTestOptions.createNodeMock;
   let isConcurrent = false;
+  let strictModeLevel = null;
   let concurrentUpdatesByDefault = null;
   if (typeof options === 'object' && options !== null) {
     if (typeof options.createNodeMock === 'function') {
@@ -444,6 +446,9 @@ function create(element: React$Element<any>, options: TestRendererOptions) {
     if (options.unstable_isConcurrent === true) {
       isConcurrent = true;
     }
+    if (options.unstable_strictMode === true) {
+      strictModeLevel = 2;
+    }
     if (allowConcurrentByDefault) {
       if (options.unstable_concurrentUpdatesByDefault !== undefined) {
         concurrentUpdatesByDefault =
@@ -461,6 +466,7 @@ function create(element: React$Element<any>, options: TestRendererOptions) {
     isConcurrent ? ConcurrentRoot : LegacyRoot,
     false,
     null,
+    strictModeLevel,
     concurrentUpdatesByDefault,
   );
   invariant(root != null, 'something went wrong');
diff --git a/packages/react/src/__tests__/ReactStrictMode-test.internal.js b/packages/react/src/__tests__/ReactStrictMode-test.internal.js
index ca651fdefaf29..b1fb0bcc270ae 100644
--- a/packages/react/src/__tests__/ReactStrictMode-test.internal.js
+++ b/packages/react/src/__tests__/ReactStrictMode-test.internal.js
@@ -65,6 +65,28 @@ describe('ReactStrictMode', () => {
     });
 
     if (__DEV__) {
+      // @gate experimental
+      it('should support enabling strict mode via createRoot option', () => {
+        act(() => {
+          const container = document.createElement('div');
+          const root = ReactDOM.createRoot(container, {
+            unstable_strictMode: true,
+          });
+          root.render(<Component label="A" />);
+        });
+
+        expect(log).toEqual([
+          'A: render',
+          'A: render',
+          'A: useLayoutEffect mount',
+          'A: useEffect mount',
+          'A: useLayoutEffect unmount',
+          'A: useEffect unmount',
+          'A: useLayoutEffect mount',
+          'A: useEffect mount',
+        ]);
+      });
+
       // @gate experimental
       it('should include legacy + strict effects mode', () => {
         act(() => {

From a11b4e50fb0718b3c1c983d47a072487623dadcf Mon Sep 17 00:00:00 2001
From: Rick Hanlon <rickhanlonii@gmail.com>
Date: Tue, 4 May 2021 15:20:11 -0400
Subject: [PATCH 2/3] Switch flag to boolean

---
 packages/react-dom/src/client/ReactDOMRoot.js       |  5 ++---
 packages/react-reconciler/src/ReactFiber.new.js     | 13 +++++--------
 packages/react-reconciler/src/ReactFiber.old.js     | 13 +++++--------
 .../src/ReactFiberReconciler.new.js                 |  4 ++--
 .../src/ReactFiberReconciler.old.js                 |  4 ++--
 packages/react-reconciler/src/ReactFiberRoot.new.js |  4 ++--
 packages/react-reconciler/src/ReactFiberRoot.old.js |  4 ++--
 .../react-test-renderer/src/ReactTestRenderer.js    |  6 +++---
 8 files changed, 23 insertions(+), 30 deletions(-)

diff --git a/packages/react-dom/src/client/ReactDOMRoot.js b/packages/react-dom/src/client/ReactDOMRoot.js
index f99c092cfd8fe..dc4c95a41ef30 100644
--- a/packages/react-dom/src/client/ReactDOMRoot.js
+++ b/packages/react-dom/src/client/ReactDOMRoot.js
@@ -123,8 +123,7 @@ function createRootImpl(
       options.hydrationOptions != null &&
       options.hydrationOptions.mutableSources) ||
     null;
-  const strictModeLevelOverride =
-    options != null && options.unstable_strictMode === true ? 2 : null;
+  const isStrictMode = options != null && options.unstable_strictMode === true;
 
   let concurrentUpdatesByDefaultOverride = null;
   if (allowConcurrentByDefault) {
@@ -139,7 +138,7 @@ function createRootImpl(
     tag,
     hydrate,
     hydrationCallbacks,
-    strictModeLevelOverride,
+    isStrictMode,
     concurrentUpdatesByDefaultOverride,
   );
   markContainerAsRoot(root.current, container);
diff --git a/packages/react-reconciler/src/ReactFiber.new.js b/packages/react-reconciler/src/ReactFiber.new.js
index 1b5afea0da661..701c2926797da 100644
--- a/packages/react-reconciler/src/ReactFiber.new.js
+++ b/packages/react-reconciler/src/ReactFiber.new.js
@@ -422,20 +422,17 @@ export function resetWorkInProgress(workInProgress: Fiber, renderLanes: Lanes) {
 
 export function createHostRootFiber(
   tag: RootTag,
-  strictModeLevelOverride: null | number,
+  isStrictMode: boolean,
   concurrentUpdatesByDefaultOverride: null | boolean,
 ): Fiber {
   let mode;
   if (tag === ConcurrentRoot) {
     mode = ConcurrentMode;
-    if (strictModeLevelOverride !== null) {
-      if (strictModeLevelOverride >= 1) {
-        mode |= StrictLegacyMode;
-      }
+    if (isStrictMode === true) {
+      mode |= StrictLegacyMode;
+
       if (enableStrictEffects) {
-        if (strictModeLevelOverride >= 2) {
-          mode |= StrictEffectsMode;
-        }
+        mode |= StrictEffectsMode;
       }
     } else if (enableStrictEffects && createRootStrictEffectsByDefault) {
       mode |= StrictLegacyMode | StrictEffectsMode;
diff --git a/packages/react-reconciler/src/ReactFiber.old.js b/packages/react-reconciler/src/ReactFiber.old.js
index 21e6affdd8a5a..fd2428b59779e 100644
--- a/packages/react-reconciler/src/ReactFiber.old.js
+++ b/packages/react-reconciler/src/ReactFiber.old.js
@@ -422,20 +422,17 @@ export function resetWorkInProgress(workInProgress: Fiber, renderLanes: Lanes) {
 
 export function createHostRootFiber(
   tag: RootTag,
-  strictModeLevelOverride: null | number,
+  isStrictMode: boolean,
   concurrentUpdatesByDefaultOverride: null | boolean,
 ): Fiber {
   let mode;
   if (tag === ConcurrentRoot) {
     mode = ConcurrentMode;
-    if (strictModeLevelOverride !== null) {
-      if (strictModeLevelOverride >= 1) {
-        mode |= StrictLegacyMode;
-      }
+    if (isStrictMode === true) {
+      mode |= StrictLegacyMode;
+
       if (enableStrictEffects) {
-        if (strictModeLevelOverride >= 2) {
-          mode |= StrictEffectsMode;
-        }
+        mode |= StrictEffectsMode;
       }
     } else if (enableStrictEffects && createRootStrictEffectsByDefault) {
       mode |= StrictLegacyMode | StrictEffectsMode;
diff --git a/packages/react-reconciler/src/ReactFiberReconciler.new.js b/packages/react-reconciler/src/ReactFiberReconciler.new.js
index f53a24e86c60b..c1e9778160a7c 100644
--- a/packages/react-reconciler/src/ReactFiberReconciler.new.js
+++ b/packages/react-reconciler/src/ReactFiberReconciler.new.js
@@ -248,7 +248,7 @@ export function createContainer(
   tag: RootTag,
   hydrate: boolean,
   hydrationCallbacks: null | SuspenseHydrationCallbacks,
-  strictModeLevelOverride: null | number,
+  isStrictMode: boolean,
   concurrentUpdatesByDefaultOverride: null | boolean,
 ): OpaqueRoot {
   return createFiberRoot(
@@ -256,7 +256,7 @@ export function createContainer(
     tag,
     hydrate,
     hydrationCallbacks,
-    strictModeLevelOverride,
+    isStrictMode,
     concurrentUpdatesByDefaultOverride,
   );
 }
diff --git a/packages/react-reconciler/src/ReactFiberReconciler.old.js b/packages/react-reconciler/src/ReactFiberReconciler.old.js
index 00c12b3406df8..47ced00130310 100644
--- a/packages/react-reconciler/src/ReactFiberReconciler.old.js
+++ b/packages/react-reconciler/src/ReactFiberReconciler.old.js
@@ -248,7 +248,7 @@ export function createContainer(
   tag: RootTag,
   hydrate: boolean,
   hydrationCallbacks: null | SuspenseHydrationCallbacks,
-  strictModeLevelOverride: null | number,
+  isStrictMode: boolean,
   concurrentUpdatesByDefaultOverride: null | boolean,
 ): OpaqueRoot {
   return createFiberRoot(
@@ -256,7 +256,7 @@ export function createContainer(
     tag,
     hydrate,
     hydrationCallbacks,
-    strictModeLevelOverride,
+    isStrictMode,
     concurrentUpdatesByDefaultOverride,
   );
 }
diff --git a/packages/react-reconciler/src/ReactFiberRoot.new.js b/packages/react-reconciler/src/ReactFiberRoot.new.js
index d2efcc5851d49..5e1f8275b694f 100644
--- a/packages/react-reconciler/src/ReactFiberRoot.new.js
+++ b/packages/react-reconciler/src/ReactFiberRoot.new.js
@@ -98,7 +98,7 @@ export function createFiberRoot(
   tag: RootTag,
   hydrate: boolean,
   hydrationCallbacks: null | SuspenseHydrationCallbacks,
-  strictModeLevelOverride: null | number,
+  isStrictMode: boolean,
   concurrentUpdatesByDefaultOverride: null | boolean,
 ): FiberRoot {
   const root: FiberRoot = (new FiberRootNode(containerInfo, tag, hydrate): any);
@@ -110,7 +110,7 @@ export function createFiberRoot(
   // stateNode is any.
   const uninitializedFiber = createHostRootFiber(
     tag,
-    strictModeLevelOverride,
+    isStrictMode,
     concurrentUpdatesByDefaultOverride,
   );
   root.current = uninitializedFiber;
diff --git a/packages/react-reconciler/src/ReactFiberRoot.old.js b/packages/react-reconciler/src/ReactFiberRoot.old.js
index 68d329492cf1b..413a87fbcffc8 100644
--- a/packages/react-reconciler/src/ReactFiberRoot.old.js
+++ b/packages/react-reconciler/src/ReactFiberRoot.old.js
@@ -98,7 +98,7 @@ export function createFiberRoot(
   tag: RootTag,
   hydrate: boolean,
   hydrationCallbacks: null | SuspenseHydrationCallbacks,
-  strictModeLevelOverride: null | number,
+  isStrictMode: boolean,
   concurrentUpdatesByDefaultOverride: null | boolean,
 ): FiberRoot {
   const root: FiberRoot = (new FiberRootNode(containerInfo, tag, hydrate): any);
@@ -110,7 +110,7 @@ export function createFiberRoot(
   // stateNode is any.
   const uninitializedFiber = createHostRootFiber(
     tag,
-    strictModeLevelOverride,
+    isStrictMode,
     concurrentUpdatesByDefaultOverride,
   );
   root.current = uninitializedFiber;
diff --git a/packages/react-test-renderer/src/ReactTestRenderer.js b/packages/react-test-renderer/src/ReactTestRenderer.js
index aa44a8d118543..246790ead3a46 100644
--- a/packages/react-test-renderer/src/ReactTestRenderer.js
+++ b/packages/react-test-renderer/src/ReactTestRenderer.js
@@ -437,7 +437,7 @@ function propsMatch(props: Object, filter: Object): boolean {
 function create(element: React$Element<any>, options: TestRendererOptions) {
   let createNodeMock = defaultTestOptions.createNodeMock;
   let isConcurrent = false;
-  let strictModeLevel = null;
+  let isStrictMode = false;
   let concurrentUpdatesByDefault = null;
   if (typeof options === 'object' && options !== null) {
     if (typeof options.createNodeMock === 'function') {
@@ -447,7 +447,7 @@ function create(element: React$Element<any>, options: TestRendererOptions) {
       isConcurrent = true;
     }
     if (options.unstable_strictMode === true) {
-      strictModeLevel = 2;
+      isStrictMode = true;
     }
     if (allowConcurrentByDefault) {
       if (options.unstable_concurrentUpdatesByDefault !== undefined) {
@@ -466,7 +466,7 @@ function create(element: React$Element<any>, options: TestRendererOptions) {
     isConcurrent ? ConcurrentRoot : LegacyRoot,
     false,
     null,
-    strictModeLevel,
+    isStrictMode,
     concurrentUpdatesByDefault,
   );
   invariant(root != null, 'something went wrong');

From b847f1fcd80d47757a403f099740e112e4c1e5c2 Mon Sep 17 00:00:00 2001
From: Rick Hanlon <rickhanlonii@gmail.com>
Date: Tue, 4 May 2021 15:37:13 -0400
Subject: [PATCH 3/3] Fix flow

---
 packages/react-native-renderer/src/ReactFabric.js         | 2 +-
 packages/react-native-renderer/src/ReactNativeRenderer.js | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/packages/react-native-renderer/src/ReactFabric.js b/packages/react-native-renderer/src/ReactFabric.js
index b319cb22c7b7b..c516452a17661 100644
--- a/packages/react-native-renderer/src/ReactFabric.js
+++ b/packages/react-native-renderer/src/ReactFabric.js
@@ -207,7 +207,7 @@ function render(
   if (!root) {
     // TODO (bvaughn): If we decide to keep the wrapper component,
     // We could create a wrapper for containerTag as well to reduce special casing.
-    root = createContainer(containerTag, LegacyRoot, false, null, null, null);
+    root = createContainer(containerTag, LegacyRoot, false, null, false, null);
     roots.set(containerTag, root);
   }
   updateContainer(element, root, null, callback);
diff --git a/packages/react-native-renderer/src/ReactNativeRenderer.js b/packages/react-native-renderer/src/ReactNativeRenderer.js
index 4f73377320378..6f12fd5d8d445 100644
--- a/packages/react-native-renderer/src/ReactNativeRenderer.js
+++ b/packages/react-native-renderer/src/ReactNativeRenderer.js
@@ -203,7 +203,7 @@ function render(
   if (!root) {
     // TODO (bvaughn): If we decide to keep the wrapper component,
     // We could create a wrapper for containerTag as well to reduce special casing.
-    root = createContainer(containerTag, LegacyRoot, false, null, null, null);
+    root = createContainer(containerTag, LegacyRoot, false, null, false, null);
     roots.set(containerTag, root);
   }
   updateContainer(element, root, null, callback);