Skip to content

Commit cc1aa9d

Browse files
committed
Move next___Hook out of global state
1 parent 3e77742 commit cc1aa9d

File tree

1 file changed

+27
-17
lines changed

1 file changed

+27
-17
lines changed

packages/react-reconciler/src/ReactFiberHooks.js

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -181,9 +181,7 @@ let currentlyRenderingFiber: Fiber | null = null;
181181
// work-in-progress hook list is a new list that will be added to the
182182
// work-in-progress fiber.
183183
let currentHook: Hook | null = null;
184-
let nextCurrentHook: Hook | null = null;
185184
let workInProgressHook: Hook | null = null;
186-
let nextWorkInProgressHook: Hook | null = null;
187185

188186
// Updates scheduled during render will trigger an immediate re-render at the
189187
// end of the current pass. We can't store these updates on the normal queue,
@@ -379,7 +377,6 @@ export function renderWithHooks(
379377
): any {
380378
renderExpirationTime = nextRenderExpirationTime;
381379
currentlyRenderingFiber = workInProgress;
382-
nextCurrentHook = current !== null ? current.memoizedState : null;
383380
384381
if (__DEV__) {
385382
hookTypesDev =
@@ -404,14 +401,14 @@ export function renderWithHooks(
404401
// renderPhaseUpdates = null;
405402
406403
// TODO Warn if no hooks are used at all during mount, then some are used during update.
407-
// Currently we will identify the update render as a mount because nextCurrentHook === null.
404+
// Currently we will identify the update render as a mount because memoizedState === null.
408405
// This is tricky because it's valid for certain types of components (e.g. React.lazy)
409406
410-
// Using nextCurrentHook to differentiate between mount/update only works if at least one stateful hook is used.
407+
// Using memoizedState to differentiate between mount/update only works if at least one stateful hook is used.
411408
// Non-stateful hooks (e.g. context) don't get added to memoizedState,
412-
// so nextCurrentHook would be null during updates and mounts.
409+
// so memoizedState would be null during updates and mounts.
413410
if (__DEV__) {
414-
if (nextCurrentHook !== null) {
411+
if (current !== null && current.memoizedState !== null) {
415412
ReactCurrentDispatcher.current = HooksDispatcherOnUpdateInDEV;
416413
} else if (hookTypesDev !== null) {
417414
// This dispatcher handles an edge case where a component is updating,
@@ -425,7 +422,7 @@ export function renderWithHooks(
425422
}
426423
} else {
427424
ReactCurrentDispatcher.current =
428-
nextCurrentHook === null
425+
current === null || current.memoizedState === null
429426
? HooksDispatcherOnMount
430427
: HooksDispatcherOnUpdate;
431428
}
@@ -452,9 +449,6 @@ export function renderWithHooks(
452449
}
453450
454451
// Start over from the beginning of the list
455-
nextCurrentHook = current !== null ? current.memoizedState : null;
456-
nextWorkInProgressHook = workInProgress.memoizedState;
457-
458452
currentHook = null;
459453
workInProgressHook = null;
460454
@@ -492,9 +486,7 @@ export function renderWithHooks(
492486
currentlyRenderingFiber = null;
493487
494488
currentHook = null;
495-
nextCurrentHook = null;
496489
workInProgressHook = null;
497-
nextWorkInProgressHook = null;
498490
499491
if (__DEV__) {
500492
currentHookNameInDev = null;
@@ -540,9 +532,7 @@ export function resetHooks(): void {
540532
currentlyRenderingFiber = null;
541533
542534
currentHook = null;
543-
nextCurrentHook = null;
544535
workInProgressHook = null;
545-
nextWorkInProgressHook = null;
546536
547537
if (__DEV__) {
548538
hookTypesDev = null;
@@ -583,15 +573,36 @@ function updateWorkInProgressHook(): Hook {
583573
// clone, or a work-in-progress hook from a previous render pass that we can
584574
// use as a base. When we reach the end of the base list, we must switch to
585575
// the dispatcher used for mounts.
576+
let nextCurrentHook: null | Hook;
577+
if (currentHook === null) {
578+
let fiber = ((currentlyRenderingFiber: any): Fiber);
579+
let current = fiber.alternate;
580+
if (current !== null) {
581+
nextCurrentHook = current.memoizedState;
582+
} else {
583+
nextCurrentHook = null;
584+
}
585+
} else {
586+
nextCurrentHook = currentHook.next;
587+
}
588+
589+
let nextWorkInProgressHook: null | Hook;
590+
if (workInProgressHook === null) {
591+
let fiber = ((currentlyRenderingFiber: any): Fiber);
592+
nextWorkInProgressHook = fiber.memoizedState;
593+
} else {
594+
nextWorkInProgressHook = workInProgressHook.next;
595+
}
596+
586597
if (nextWorkInProgressHook !== null) {
587598
// There's already a work-in-progress. Reuse it.
588599
workInProgressHook = nextWorkInProgressHook;
589600
nextWorkInProgressHook = workInProgressHook.next;
590601
591602
currentHook = nextCurrentHook;
592-
nextCurrentHook = currentHook !== null ? currentHook.next : null;
593603
} else {
594604
// Clone from the current hook.
605+
595606
invariant(
596607
nextCurrentHook !== null,
597608
'Rendered more hooks than during the previous render.',
@@ -616,7 +627,6 @@ function updateWorkInProgressHook(): Hook {
616627
// Append to the end of the list.
617628
workInProgressHook = workInProgressHook.next = newHook;
618629
}
619-
nextCurrentHook = currentHook.next;
620630
}
621631
return workInProgressHook;
622632
}

0 commit comments

Comments
 (0)