Skip to content

Commit 3e5228f

Browse files
authored
Merge pull request #46 from facebook/master
Add StrictMode level prop and createRoot unstable_strictModeLevel opt…
2 parents a94cbdb + 9209c30 commit 3e5228f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+1243
-934
lines changed

packages/react-dom/src/client/ReactDOMRoot.js

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export type RootOptions = {
2727
mutableSources?: Array<MutableSource<any>>,
2828
...
2929
},
30+
unstable_strictModeLevel?: number,
3031
...
3132
};
3233

@@ -128,7 +129,18 @@ function createRootImpl(
128129
options.hydrationOptions != null &&
129130
options.hydrationOptions.mutableSources) ||
130131
null;
131-
const root = createContainer(container, tag, hydrate, hydrationCallbacks);
132+
const strictModeLevelOverride =
133+
options != null && options.unstable_strictModeLevel != null
134+
? options.unstable_strictModeLevel
135+
: null;
136+
137+
const root = createContainer(
138+
container,
139+
tag,
140+
hydrate,
141+
hydrationCallbacks,
142+
strictModeLevelOverride,
143+
);
132144
markContainerAsRoot(root.current, container);
133145

134146
const rootContainerElement =

packages/react-native-renderer/src/ReactFabric.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ function render(
203203
if (!root) {
204204
// TODO (bvaughn): If we decide to keep the wrapper component,
205205
// We could create a wrapper for containerTag as well to reduce special casing.
206-
root = createContainer(containerTag, LegacyRoot, false, null);
206+
root = createContainer(containerTag, LegacyRoot, false, null, null);
207207
roots.set(containerTag, root);
208208
}
209209
updateContainer(element, root, null, callback);

packages/react-native-renderer/src/ReactNativeRenderer.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ function render(
202202
if (!root) {
203203
// TODO (bvaughn): If we decide to keep the wrapper component,
204204
// We could create a wrapper for containerTag as well to reduce special casing.
205-
root = createContainer(containerTag, LegacyRoot, false, null);
205+
root = createContainer(containerTag, LegacyRoot, false, null, null);
206206
roots.set(containerTag, root);
207207
}
208208
updateContainer(element, root, null, callback);

packages/react-noop-renderer/src/createReactNoop.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -722,7 +722,7 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
722722
if (!root) {
723723
const container = {rootID: rootID, pendingChildren: [], children: []};
724724
rootContainers.set(rootID, container);
725-
root = NoopRenderer.createContainer(container, tag, false, null);
725+
root = NoopRenderer.createContainer(container, tag, false, null, null);
726726
roots.set(rootID, root);
727727
}
728728
return root.current.stateNode.containerInfo;
@@ -740,6 +740,7 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
740740
ConcurrentRoot,
741741
false,
742742
null,
743+
null,
743744
);
744745
return {
745746
_Scheduler: Scheduler,
@@ -766,6 +767,7 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
766767
BlockingRoot,
767768
false,
768769
null,
770+
null,
769771
);
770772
return {
771773
_Scheduler: Scheduler,
@@ -792,6 +794,7 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
792794
LegacyRoot,
793795
false,
794796
null,
797+
null,
795798
);
796799
return {
797800
_Scheduler: Scheduler,

packages/react-reconciler/src/ReactChildFiber.new.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ import {
4646
} from './ReactFiber.new';
4747
import {emptyRefsObject} from './ReactFiberClassComponent.new';
4848
import {isCompatibleFamilyForHotReloading} from './ReactFiberHotReloading.new';
49-
import {StrictMode} from './ReactTypeOfMode';
49+
import {StrictLegacyMode} from './ReactTypeOfMode';
5050

5151
let didWarnAboutMaps;
5252
let didWarnAboutGenerators;
@@ -114,7 +114,7 @@ function coerceRef(
114114
// TODO: Clean this up once we turn on the string ref warning for
115115
// everyone, because the strict mode case will no longer be relevant
116116
if (
117-
(returnFiber.mode & StrictMode || warnAboutStringRefs) &&
117+
(returnFiber.mode & StrictLegacyMode || warnAboutStringRefs) &&
118118
// We warn in ReactElement.js if owner and self are equal for string refs
119119
// because these cannot be automatically converted to an arrow function
120120
// using a codemod. Therefore, we don't have to warn about string refs again.

packages/react-reconciler/src/ReactChildFiber.old.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ import {
4646
} from './ReactFiber.old';
4747
import {emptyRefsObject} from './ReactFiberClassComponent.old';
4848
import {isCompatibleFamilyForHotReloading} from './ReactFiberHotReloading.old';
49-
import {StrictMode} from './ReactTypeOfMode';
49+
import {StrictLegacyMode} from './ReactTypeOfMode';
5050

5151
let didWarnAboutMaps;
5252
let didWarnAboutGenerators;
@@ -114,7 +114,7 @@ function coerceRef(
114114
// TODO: Clean this up once we turn on the string ref warning for
115115
// everyone, because the strict mode case will no longer be relevant
116116
if (
117-
(returnFiber.mode & StrictMode || warnAboutStringRefs) &&
117+
(returnFiber.mode & StrictLegacyMode || warnAboutStringRefs) &&
118118
// We warn in ReactElement.js if owner and self are equal for string refs
119119
// because these cannot be automatically converted to an arrow function
120120
// using a codemod. Therefore, we don't have to warn about string refs again.

packages/react-reconciler/src/ReactFiber.new.js

Lines changed: 58 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,11 @@ import type {OffscreenProps} from './ReactFiberOffscreenComponent';
1919

2020
import invariant from 'shared/invariant';
2121
import {
22+
createRootStrictEffectsByDefault,
23+
enableCache,
24+
enableStrictEffects,
2225
enableProfilerTimer,
2326
enableScopeAPI,
24-
enableCache,
2527
} from 'shared/ReactFeatureFlags';
2628
import {NoFlags, Placement, StaticMask} from './ReactFiberFlags';
2729
import {ConcurrentRoot, BlockingRoot} from './ReactRootTags';
@@ -64,7 +66,8 @@ import {
6466
ConcurrentMode,
6567
DebugTracingMode,
6668
ProfileMode,
67-
StrictMode,
69+
StrictLegacyMode,
70+
StrictEffectsMode,
6871
BlockingMode,
6972
} from './ReactTypeOfMode';
7073
import {
@@ -418,12 +421,47 @@ export function resetWorkInProgress(workInProgress: Fiber, renderLanes: Lanes) {
418421
return workInProgress;
419422
}
420423

421-
export function createHostRootFiber(tag: RootTag): Fiber {
424+
export function createHostRootFiber(
425+
tag: RootTag,
426+
strictModeLevelOverride: null | number,
427+
): Fiber {
422428
let mode;
423429
if (tag === ConcurrentRoot) {
424-
mode = ConcurrentMode | BlockingMode | StrictMode;
430+
mode = ConcurrentMode | BlockingMode;
431+
if (strictModeLevelOverride !== null) {
432+
if (strictModeLevelOverride >= 1) {
433+
mode |= StrictLegacyMode;
434+
}
435+
if (enableStrictEffects) {
436+
if (strictModeLevelOverride >= 2) {
437+
mode |= StrictEffectsMode;
438+
}
439+
}
440+
} else {
441+
if (enableStrictEffects && createRootStrictEffectsByDefault) {
442+
mode |= StrictLegacyMode | StrictEffectsMode;
443+
} else {
444+
mode |= StrictLegacyMode;
445+
}
446+
}
425447
} else if (tag === BlockingRoot) {
426-
mode = BlockingMode | StrictMode;
448+
mode = BlockingMode;
449+
if (strictModeLevelOverride !== null) {
450+
if (strictModeLevelOverride >= 1) {
451+
mode |= StrictLegacyMode;
452+
}
453+
if (enableStrictEffects) {
454+
if (strictModeLevelOverride >= 2) {
455+
mode |= StrictEffectsMode;
456+
}
457+
}
458+
} else {
459+
if (enableStrictEffects && createRootStrictEffectsByDefault) {
460+
mode |= StrictLegacyMode | StrictEffectsMode;
461+
} else {
462+
mode |= StrictLegacyMode;
463+
}
464+
}
427465
} else {
428466
mode = NoMode;
429467
}
@@ -472,7 +510,21 @@ export function createFiberFromTypeAndProps(
472510
break;
473511
case REACT_STRICT_MODE_TYPE:
474512
fiberTag = Mode;
475-
mode |= StrictMode;
513+
514+
// Legacy strict mode (<StrictMode> without any level prop) defaults to level 1.
515+
const level =
516+
pendingProps.unstable_level == null ? 1 : pendingProps.unstable_level;
517+
518+
// Levels cascade; higher levels inherit all lower level modes.
519+
// It is explicitly not supported to lower a mode with nesting, only to increase it.
520+
if (level >= 1) {
521+
mode |= StrictLegacyMode;
522+
}
523+
if (enableStrictEffects) {
524+
if (level >= 2) {
525+
mode |= StrictEffectsMode;
526+
}
527+
}
476528
break;
477529
case REACT_PROFILER_TYPE:
478530
return createFiberFromProfiler(pendingProps, mode, lanes, key);

packages/react-reconciler/src/ReactFiber.old.js

Lines changed: 58 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,11 @@ import type {OffscreenProps} from './ReactFiberOffscreenComponent';
1919

2020
import invariant from 'shared/invariant';
2121
import {
22+
createRootStrictEffectsByDefault,
23+
enableCache,
24+
enableStrictEffects,
2225
enableProfilerTimer,
2326
enableScopeAPI,
24-
enableCache,
2527
} from 'shared/ReactFeatureFlags';
2628
import {NoFlags, Placement, StaticMask} from './ReactFiberFlags';
2729
import {ConcurrentRoot, BlockingRoot} from './ReactRootTags';
@@ -64,7 +66,8 @@ import {
6466
ConcurrentMode,
6567
DebugTracingMode,
6668
ProfileMode,
67-
StrictMode,
69+
StrictLegacyMode,
70+
StrictEffectsMode,
6871
BlockingMode,
6972
} from './ReactTypeOfMode';
7073
import {
@@ -418,12 +421,47 @@ export function resetWorkInProgress(workInProgress: Fiber, renderLanes: Lanes) {
418421
return workInProgress;
419422
}
420423

421-
export function createHostRootFiber(tag: RootTag): Fiber {
424+
export function createHostRootFiber(
425+
tag: RootTag,
426+
strictModeLevelOverride: null | number,
427+
): Fiber {
422428
let mode;
423429
if (tag === ConcurrentRoot) {
424-
mode = ConcurrentMode | BlockingMode | StrictMode;
430+
mode = ConcurrentMode | BlockingMode;
431+
if (strictModeLevelOverride !== null) {
432+
if (strictModeLevelOverride >= 1) {
433+
mode |= StrictLegacyMode;
434+
}
435+
if (enableStrictEffects) {
436+
if (strictModeLevelOverride >= 2) {
437+
mode |= StrictEffectsMode;
438+
}
439+
}
440+
} else {
441+
if (enableStrictEffects && createRootStrictEffectsByDefault) {
442+
mode |= StrictLegacyMode | StrictEffectsMode;
443+
} else {
444+
mode |= StrictLegacyMode;
445+
}
446+
}
425447
} else if (tag === BlockingRoot) {
426-
mode = BlockingMode | StrictMode;
448+
mode = BlockingMode;
449+
if (strictModeLevelOverride !== null) {
450+
if (strictModeLevelOverride >= 1) {
451+
mode |= StrictLegacyMode;
452+
}
453+
if (enableStrictEffects) {
454+
if (strictModeLevelOverride >= 2) {
455+
mode |= StrictEffectsMode;
456+
}
457+
}
458+
} else {
459+
if (enableStrictEffects && createRootStrictEffectsByDefault) {
460+
mode |= StrictLegacyMode | StrictEffectsMode;
461+
} else {
462+
mode |= StrictLegacyMode;
463+
}
464+
}
427465
} else {
428466
mode = NoMode;
429467
}
@@ -472,7 +510,21 @@ export function createFiberFromTypeAndProps(
472510
break;
473511
case REACT_STRICT_MODE_TYPE:
474512
fiberTag = Mode;
475-
mode |= StrictMode;
513+
514+
// Legacy strict mode (<StrictMode> without any level prop) defaults to level 1.
515+
const level =
516+
pendingProps.unstable_level == null ? 1 : pendingProps.unstable_level;
517+
518+
// Levels cascade; higher levels inherit all lower level modes.
519+
// It is explicitly not supported to lower a mode with nesting, only to increase it.
520+
if (level >= 1) {
521+
mode |= StrictLegacyMode;
522+
}
523+
if (enableStrictEffects) {
524+
if (level >= 2) {
525+
mode |= StrictEffectsMode;
526+
}
527+
}
476528
break;
477529
case REACT_PROFILER_TYPE:
478530
return createFiberFromProfiler(pendingProps, mode, lanes, key);

packages/react-reconciler/src/ReactFiberBeginWork.new.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ import {
125125
ConcurrentMode,
126126
NoMode,
127127
ProfileMode,
128-
StrictMode,
128+
StrictLegacyMode,
129129
BlockingMode,
130130
} from './ReactTypeOfMode';
131131
import {
@@ -357,7 +357,7 @@ function updateForwardRef(
357357
);
358358
if (
359359
debugRenderPhaseSideEffectsForStrictMode &&
360-
workInProgress.mode & StrictMode
360+
workInProgress.mode & StrictLegacyMode
361361
) {
362362
disableLogs();
363363
try {
@@ -889,7 +889,7 @@ function updateFunctionComponent(
889889
);
890890
if (
891891
debugRenderPhaseSideEffectsForStrictMode &&
892-
workInProgress.mode & StrictMode
892+
workInProgress.mode & StrictLegacyMode
893893
) {
894894
disableLogs();
895895
try {
@@ -1068,7 +1068,7 @@ function finishClassComponent(
10681068
nextChildren = instance.render();
10691069
if (
10701070
debugRenderPhaseSideEffectsForStrictMode &&
1071-
workInProgress.mode & StrictMode
1071+
workInProgress.mode & StrictLegacyMode
10721072
) {
10731073
disableLogs();
10741074
try {
@@ -1478,7 +1478,7 @@ function mountIndeterminateComponent(
14781478
}
14791479
}
14801480

1481-
if (workInProgress.mode & StrictMode) {
1481+
if (workInProgress.mode & StrictLegacyMode) {
14821482
ReactStrictModeWarnings.recordLegacyContextWarning(workInProgress, null);
14831483
}
14841484

@@ -1615,7 +1615,7 @@ function mountIndeterminateComponent(
16151615

16161616
if (
16171617
debugRenderPhaseSideEffectsForStrictMode &&
1618-
workInProgress.mode & StrictMode
1618+
workInProgress.mode & StrictLegacyMode
16191619
) {
16201620
disableLogs();
16211621
try {

0 commit comments

Comments
 (0)