Skip to content

Commit a502113

Browse files
gaearonrickhanlonii
authored andcommitted
Fix warning about setState in useEffect (#24295)
* Fix warning about setState in useEffect * Fix test * Fix multiple roots
1 parent 03d8b55 commit a502113

File tree

2 files changed

+68
-8
lines changed

2 files changed

+68
-8
lines changed

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

+34-4
Original file line numberDiff line numberDiff line change
@@ -396,9 +396,12 @@ let pendingPassiveEffectsRemainingLanes: Lanes = NoLanes;
396396
const NESTED_UPDATE_LIMIT = 50;
397397
let nestedUpdateCount: number = 0;
398398
let rootWithNestedUpdates: FiberRoot | null = null;
399+
let isFlushingPassiveEffects = false;
400+
let didScheduleUpdateDuringPassiveEffects = false;
399401

400402
const NESTED_PASSIVE_UPDATE_LIMIT = 50;
401403
let nestedPassiveUpdateCount: number = 0;
404+
let rootWithPassiveNestedUpdates: FiberRoot | null = null;
402405

403406
// If two updates are scheduled within the same event, we should treat their
404407
// event times as simultaneous, even if the actual clock time has advanced
@@ -522,6 +525,12 @@ export function scheduleUpdateOnFiber(
522525
return null;
523526
}
524527

528+
if (__DEV__) {
529+
if (isFlushingPassiveEffects) {
530+
didScheduleUpdateDuringPassiveEffects = true;
531+
}
532+
}
533+
525534
// Mark that the root has a pending update.
526535
markRootUpdated(root, lane, eventTime);
527536

@@ -2204,6 +2213,10 @@ function commitRootImpl(
22042213
// There were no passive effects, so we can immediately release the cache
22052214
// pool for this render.
22062215
releaseRootPooledCache(root, remainingLanes);
2216+
if (__DEV__) {
2217+
nestedPassiveUpdateCount = 0;
2218+
rootWithPassiveNestedUpdates = null;
2219+
}
22072220
}
22082221

22092222
// Read this again, since an effect might have updated it
@@ -2420,6 +2433,9 @@ function flushPassiveEffectsImpl() {
24202433
}
24212434

24222435
if (__DEV__) {
2436+
isFlushingPassiveEffects = true;
2437+
didScheduleUpdateDuringPassiveEffects = false;
2438+
24232439
if (enableDebugTracing) {
24242440
logPassiveEffectsStarted(lanes);
24252441
}
@@ -2463,10 +2479,22 @@ function flushPassiveEffectsImpl() {
24632479

24642480
flushSyncCallbacks();
24652481

2466-
// If additional passive effects were scheduled, increment a counter. If this
2467-
// exceeds the limit, we'll fire a warning.
2468-
nestedPassiveUpdateCount =
2469-
rootWithPendingPassiveEffects === null ? 0 : nestedPassiveUpdateCount + 1;
2482+
if (__DEV__) {
2483+
// If additional passive effects were scheduled, increment a counter. If this
2484+
// exceeds the limit, we'll fire a warning.
2485+
if (didScheduleUpdateDuringPassiveEffects) {
2486+
if (root === rootWithPassiveNestedUpdates) {
2487+
nestedPassiveUpdateCount++;
2488+
} else {
2489+
nestedPassiveUpdateCount = 0;
2490+
rootWithPassiveNestedUpdates = root;
2491+
}
2492+
} else {
2493+
nestedPassiveUpdateCount = 0;
2494+
}
2495+
isFlushingPassiveEffects = false;
2496+
didScheduleUpdateDuringPassiveEffects = false;
2497+
}
24702498

24712499
// TODO: Move to commitPassiveMountEffects
24722500
onPostCommitRootDevTools(root);
@@ -2739,6 +2767,8 @@ function checkForNestedUpdates() {
27392767
if (__DEV__) {
27402768
if (nestedPassiveUpdateCount > NESTED_PASSIVE_UPDATE_LIMIT) {
27412769
nestedPassiveUpdateCount = 0;
2770+
rootWithPassiveNestedUpdates = null;
2771+
27422772
console.error(
27432773
'Maximum update depth exceeded. This can happen when a component ' +
27442774
"calls setState inside useEffect, but useEffect either doesn't " +

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

+34-4
Original file line numberDiff line numberDiff line change
@@ -396,9 +396,12 @@ let pendingPassiveEffectsRemainingLanes: Lanes = NoLanes;
396396
const NESTED_UPDATE_LIMIT = 50;
397397
let nestedUpdateCount: number = 0;
398398
let rootWithNestedUpdates: FiberRoot | null = null;
399+
let isFlushingPassiveEffects = false;
400+
let didScheduleUpdateDuringPassiveEffects = false;
399401

400402
const NESTED_PASSIVE_UPDATE_LIMIT = 50;
401403
let nestedPassiveUpdateCount: number = 0;
404+
let rootWithPassiveNestedUpdates: FiberRoot | null = null;
402405

403406
// If two updates are scheduled within the same event, we should treat their
404407
// event times as simultaneous, even if the actual clock time has advanced
@@ -522,6 +525,12 @@ export function scheduleUpdateOnFiber(
522525
return null;
523526
}
524527

528+
if (__DEV__) {
529+
if (isFlushingPassiveEffects) {
530+
didScheduleUpdateDuringPassiveEffects = true;
531+
}
532+
}
533+
525534
// Mark that the root has a pending update.
526535
markRootUpdated(root, lane, eventTime);
527536

@@ -2204,6 +2213,10 @@ function commitRootImpl(
22042213
// There were no passive effects, so we can immediately release the cache
22052214
// pool for this render.
22062215
releaseRootPooledCache(root, remainingLanes);
2216+
if (__DEV__) {
2217+
nestedPassiveUpdateCount = 0;
2218+
rootWithPassiveNestedUpdates = null;
2219+
}
22072220
}
22082221

22092222
// Read this again, since an effect might have updated it
@@ -2420,6 +2433,9 @@ function flushPassiveEffectsImpl() {
24202433
}
24212434

24222435
if (__DEV__) {
2436+
isFlushingPassiveEffects = true;
2437+
didScheduleUpdateDuringPassiveEffects = false;
2438+
24232439
if (enableDebugTracing) {
24242440
logPassiveEffectsStarted(lanes);
24252441
}
@@ -2463,10 +2479,22 @@ function flushPassiveEffectsImpl() {
24632479

24642480
flushSyncCallbacks();
24652481

2466-
// If additional passive effects were scheduled, increment a counter. If this
2467-
// exceeds the limit, we'll fire a warning.
2468-
nestedPassiveUpdateCount =
2469-
rootWithPendingPassiveEffects === null ? 0 : nestedPassiveUpdateCount + 1;
2482+
if (__DEV__) {
2483+
// If additional passive effects were scheduled, increment a counter. If this
2484+
// exceeds the limit, we'll fire a warning.
2485+
if (didScheduleUpdateDuringPassiveEffects) {
2486+
if (root === rootWithPassiveNestedUpdates) {
2487+
nestedPassiveUpdateCount++;
2488+
} else {
2489+
nestedPassiveUpdateCount = 0;
2490+
rootWithPassiveNestedUpdates = root;
2491+
}
2492+
} else {
2493+
nestedPassiveUpdateCount = 0;
2494+
}
2495+
isFlushingPassiveEffects = false;
2496+
didScheduleUpdateDuringPassiveEffects = false;
2497+
}
24702498

24712499
// TODO: Move to commitPassiveMountEffects
24722500
onPostCommitRootDevTools(root);
@@ -2739,6 +2767,8 @@ function checkForNestedUpdates() {
27392767
if (__DEV__) {
27402768
if (nestedPassiveUpdateCount > NESTED_PASSIVE_UPDATE_LIMIT) {
27412769
nestedPassiveUpdateCount = 0;
2770+
rootWithPassiveNestedUpdates = null;
2771+
27422772
console.error(
27432773
'Maximum update depth exceeded. This can happen when a component ' +
27442774
"calls setState inside useEffect, but useEffect either doesn't " +

0 commit comments

Comments
 (0)