From baac940c3222451cba70af14d456da87b3c87b24 Mon Sep 17 00:00:00 2001 From: Samuel Susla Date: Mon, 21 Nov 2022 15:06:07 +0000 Subject: [PATCH 1/3] Add component name to StrictMode error message --- .../react-reconciler/src/ReactFiberClassUpdateQueue.new.js | 5 ++++- .../react-reconciler/src/ReactFiberClassUpdateQueue.old.js | 5 ++++- .../src/__tests__/ReactIncrementalUpdates-test.js | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/react-reconciler/src/ReactFiberClassUpdateQueue.new.js b/packages/react-reconciler/src/ReactFiberClassUpdateQueue.new.js index 6ad50d8130571..e1acb4b7ed67c 100644 --- a/packages/react-reconciler/src/ReactFiberClassUpdateQueue.new.js +++ b/packages/react-reconciler/src/ReactFiberClassUpdateQueue.new.js @@ -108,6 +108,7 @@ import { ShouldCapture, DidCapture, } from './ReactFiberFlags'; +import getComponentNameFromFiber from 'react-reconciler/src/getComponentNameFromFiber'; import {debugRenderPhaseSideEffectsForStrictMode} from 'shared/ReactFeatureFlags'; @@ -239,11 +240,13 @@ export function enqueueUpdate( currentlyProcessingQueue === sharedQueue && !didWarnUpdateInsideUpdate ) { + const componentName = getComponentNameFromFiber(fiber); console.error( 'An update (setState, replaceState, or forceUpdate) was scheduled ' + 'from inside an update function. Update functions should be pure, ' + 'with zero side-effects. Consider using componentDidUpdate or a ' + - 'callback.', + 'callback.\n\nPlease update the following component: %s', + componentName, ); didWarnUpdateInsideUpdate = true; } diff --git a/packages/react-reconciler/src/ReactFiberClassUpdateQueue.old.js b/packages/react-reconciler/src/ReactFiberClassUpdateQueue.old.js index c008976d54095..b2021a10f73ac 100644 --- a/packages/react-reconciler/src/ReactFiberClassUpdateQueue.old.js +++ b/packages/react-reconciler/src/ReactFiberClassUpdateQueue.old.js @@ -108,6 +108,7 @@ import { ShouldCapture, DidCapture, } from './ReactFiberFlags'; +import getComponentNameFromFiber from 'react-reconciler/src/getComponentNameFromFiber'; import {debugRenderPhaseSideEffectsForStrictMode} from 'shared/ReactFeatureFlags'; @@ -239,11 +240,13 @@ export function enqueueUpdate( currentlyProcessingQueue === sharedQueue && !didWarnUpdateInsideUpdate ) { + const componentName = getComponentNameFromFiber(fiber); console.error( 'An update (setState, replaceState, or forceUpdate) was scheduled ' + 'from inside an update function. Update functions should be pure, ' + 'with zero side-effects. Consider using componentDidUpdate or a ' + - 'callback.', + 'callback.\n\nPlease update the following component: %s', + componentName, ); didWarnUpdateInsideUpdate = true; } diff --git a/packages/react-reconciler/src/__tests__/ReactIncrementalUpdates-test.js b/packages/react-reconciler/src/__tests__/ReactIncrementalUpdates-test.js index 454a0399b9a52..4d667b0ab6707 100644 --- a/packages/react-reconciler/src/__tests__/ReactIncrementalUpdates-test.js +++ b/packages/react-reconciler/src/__tests__/ReactIncrementalUpdates-test.js @@ -474,7 +474,7 @@ describe('ReactIncrementalUpdates', () => { 'An update (setState, replaceState, or forceUpdate) was scheduled ' + 'from inside an update function. Update functions should be pure, ' + 'with zero side-effects. Consider using componentDidUpdate or a ' + - 'callback.', + 'callback.\n\nPlease update the following component: Foo', ); expect(instance.state).toEqual({a: 'a', b: 'b'}); From 497133767438277854264343b50bdb7e7cc2322a Mon Sep 17 00:00:00 2001 From: Samuel Susla Date: Fri, 2 Dec 2022 15:36:58 +0000 Subject: [PATCH 2/3] Remove forked file --- .../src/ReactFiberClassUpdateQueue.old.js | 745 ------------------ 1 file changed, 745 deletions(-) delete mode 100644 packages/react-reconciler/src/ReactFiberClassUpdateQueue.old.js diff --git a/packages/react-reconciler/src/ReactFiberClassUpdateQueue.old.js b/packages/react-reconciler/src/ReactFiberClassUpdateQueue.old.js deleted file mode 100644 index b2021a10f73ac..0000000000000 --- a/packages/react-reconciler/src/ReactFiberClassUpdateQueue.old.js +++ /dev/null @@ -1,745 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow - */ - -// UpdateQueue is a linked list of prioritized updates. -// -// Like fibers, update queues come in pairs: a current queue, which represents -// the visible state of the screen, and a work-in-progress queue, which can be -// mutated and processed asynchronously before it is committed — a form of -// double buffering. If a work-in-progress render is discarded before finishing, -// we create a new work-in-progress by cloning the current queue. -// -// Both queues share a persistent, singly-linked list structure. To schedule an -// update, we append it to the end of both queues. Each queue maintains a -// pointer to first update in the persistent list that hasn't been processed. -// The work-in-progress pointer always has a position equal to or greater than -// the current queue, since we always work on that one. The current queue's -// pointer is only updated during the commit phase, when we swap in the -// work-in-progress. -// -// For example: -// -// Current pointer: A - B - C - D - E - F -// Work-in-progress pointer: D - E - F -// ^ -// The work-in-progress queue has -// processed more updates than current. -// -// The reason we append to both queues is because otherwise we might drop -// updates without ever processing them. For example, if we only add updates to -// the work-in-progress queue, some updates could be lost whenever a work-in -// -progress render restarts by cloning from current. Similarly, if we only add -// updates to the current queue, the updates will be lost whenever an already -// in-progress queue commits and swaps with the current queue. However, by -// adding to both queues, we guarantee that the update will be part of the next -// work-in-progress. (And because the work-in-progress queue becomes the -// current queue once it commits, there's no danger of applying the same -// update twice.) -// -// Prioritization -// -------------- -// -// Updates are not sorted by priority, but by insertion; new updates are always -// appended to the end of the list. -// -// The priority is still important, though. When processing the update queue -// during the render phase, only the updates with sufficient priority are -// included in the result. If we skip an update because it has insufficient -// priority, it remains in the queue to be processed later, during a lower -// priority render. Crucially, all updates subsequent to a skipped update also -// remain in the queue *regardless of their priority*. That means high priority -// updates are sometimes processed twice, at two separate priorities. We also -// keep track of a base state, that represents the state before the first -// update in the queue is applied. -// -// For example: -// -// Given a base state of '', and the following queue of updates -// -// A1 - B2 - C1 - D2 -// -// where the number indicates the priority, and the update is applied to the -// previous state by appending a letter, React will process these updates as -// two separate renders, one per distinct priority level: -// -// First render, at priority 1: -// Base state: '' -// Updates: [A1, C1] -// Result state: 'AC' -// -// Second render, at priority 2: -// Base state: 'A' <- The base state does not include C1, -// because B2 was skipped. -// Updates: [B2, C1, D2] <- C1 was rebased on top of B2 -// Result state: 'ABCD' -// -// Because we process updates in insertion order, and rebase high priority -// updates when preceding updates are skipped, the final result is deterministic -// regardless of priority. Intermediate state may vary according to system -// resources, but the final state is always the same. - -import type {Fiber, FiberRoot} from './ReactInternalTypes'; -import type {Lanes, Lane} from './ReactFiberLane.old'; - -import { - NoLane, - NoLanes, - OffscreenLane, - isSubsetOfLanes, - mergeLanes, - removeLanes, - isTransitionLane, - intersectLanes, - markRootEntangled, -} from './ReactFiberLane.old'; -import { - enterDisallowedContextReadInDEV, - exitDisallowedContextReadInDEV, -} from './ReactFiberNewContext.old'; -import { - Callback, - Visibility, - ShouldCapture, - DidCapture, -} from './ReactFiberFlags'; -import getComponentNameFromFiber from 'react-reconciler/src/getComponentNameFromFiber'; - -import {debugRenderPhaseSideEffectsForStrictMode} from 'shared/ReactFeatureFlags'; - -import {StrictLegacyMode} from './ReactTypeOfMode'; -import { - markSkippedUpdateLanes, - isUnsafeClassRenderPhaseUpdate, - getWorkInProgressRootRenderLanes, -} from './ReactFiberWorkLoop.old'; -import { - enqueueConcurrentClassUpdate, - unsafe_markUpdateLaneFromFiberToRoot, -} from './ReactFiberConcurrentUpdates.old'; -import {setIsStrictModeForDevtools} from './ReactFiberDevToolsHook.old'; - -import assign from 'shared/assign'; - -export type Update = { - // TODO: Temporary field. Will remove this by storing a map of - // transition -> event time on the root. - eventTime: number, - lane: Lane, - - tag: 0 | 1 | 2 | 3, - payload: any, - callback: (() => mixed) | null, - - next: Update | null, -}; - -export type SharedQueue = { - pending: Update | null, - lanes: Lanes, - hiddenCallbacks: Array<() => mixed> | null, -}; - -export type UpdateQueue = { - baseState: State, - firstBaseUpdate: Update | null, - lastBaseUpdate: Update | null, - shared: SharedQueue, - callbacks: Array<() => mixed> | null, -}; - -export const UpdateState = 0; -export const ReplaceState = 1; -export const ForceUpdate = 2; -export const CaptureUpdate = 3; - -// Global state that is reset at the beginning of calling `processUpdateQueue`. -// It should only be read right after calling `processUpdateQueue`, via -// `checkHasForceUpdateAfterProcessing`. -let hasForceUpdate = false; - -let didWarnUpdateInsideUpdate; -let currentlyProcessingQueue; -export let resetCurrentlyProcessingQueue: () => void; -if (__DEV__) { - didWarnUpdateInsideUpdate = false; - currentlyProcessingQueue = null; - resetCurrentlyProcessingQueue = () => { - currentlyProcessingQueue = null; - }; -} - -export function initializeUpdateQueue(fiber: Fiber): void { - const queue: UpdateQueue = { - baseState: fiber.memoizedState, - firstBaseUpdate: null, - lastBaseUpdate: null, - shared: { - pending: null, - lanes: NoLanes, - hiddenCallbacks: null, - }, - callbacks: null, - }; - fiber.updateQueue = queue; -} - -export function cloneUpdateQueue( - current: Fiber, - workInProgress: Fiber, -): void { - // Clone the update queue from current. Unless it's already a clone. - const queue: UpdateQueue = (workInProgress.updateQueue: any); - const currentQueue: UpdateQueue = (current.updateQueue: any); - if (queue === currentQueue) { - const clone: UpdateQueue = { - baseState: currentQueue.baseState, - firstBaseUpdate: currentQueue.firstBaseUpdate, - lastBaseUpdate: currentQueue.lastBaseUpdate, - shared: currentQueue.shared, - callbacks: null, - }; - workInProgress.updateQueue = clone; - } -} - -export function createUpdate(eventTime: number, lane: Lane): Update { - const update: Update = { - eventTime, - lane, - - tag: UpdateState, - payload: null, - callback: null, - - next: null, - }; - return update; -} - -export function enqueueUpdate( - fiber: Fiber, - update: Update, - lane: Lane, -): FiberRoot | null { - const updateQueue = fiber.updateQueue; - if (updateQueue === null) { - // Only occurs if the fiber has been unmounted. - return null; - } - - const sharedQueue: SharedQueue = (updateQueue: any).shared; - - if (__DEV__) { - if ( - currentlyProcessingQueue === sharedQueue && - !didWarnUpdateInsideUpdate - ) { - const componentName = getComponentNameFromFiber(fiber); - console.error( - 'An update (setState, replaceState, or forceUpdate) was scheduled ' + - 'from inside an update function. Update functions should be pure, ' + - 'with zero side-effects. Consider using componentDidUpdate or a ' + - 'callback.\n\nPlease update the following component: %s', - componentName, - ); - didWarnUpdateInsideUpdate = true; - } - } - - if (isUnsafeClassRenderPhaseUpdate(fiber)) { - // This is an unsafe render phase update. Add directly to the update - // queue so we can process it immediately during the current render. - const pending = sharedQueue.pending; - if (pending === null) { - // This is the first update. Create a circular list. - update.next = update; - } else { - update.next = pending.next; - pending.next = update; - } - sharedQueue.pending = update; - - // Update the childLanes even though we're most likely already rendering - // this fiber. This is for backwards compatibility in the case where you - // update a different component during render phase than the one that is - // currently renderings (a pattern that is accompanied by a warning). - return unsafe_markUpdateLaneFromFiberToRoot(fiber, lane); - } else { - return enqueueConcurrentClassUpdate(fiber, sharedQueue, update, lane); - } -} - -export function entangleTransitions(root: FiberRoot, fiber: Fiber, lane: Lane) { - const updateQueue = fiber.updateQueue; - if (updateQueue === null) { - // Only occurs if the fiber has been unmounted. - return; - } - - const sharedQueue: SharedQueue = (updateQueue: any).shared; - if (isTransitionLane(lane)) { - let queueLanes = sharedQueue.lanes; - - // If any entangled lanes are no longer pending on the root, then they must - // have finished. We can remove them from the shared queue, which represents - // a superset of the actually pending lanes. In some cases we may entangle - // more than we need to, but that's OK. In fact it's worse if we *don't* - // entangle when we should. - queueLanes = intersectLanes(queueLanes, root.pendingLanes); - - // Entangle the new transition lane with the other transition lanes. - const newQueueLanes = mergeLanes(queueLanes, lane); - sharedQueue.lanes = newQueueLanes; - // Even if queue.lanes already include lane, we don't know for certain if - // the lane finished since the last time we entangled it. So we need to - // entangle it again, just to be sure. - markRootEntangled(root, newQueueLanes); - } -} - -export function enqueueCapturedUpdate( - workInProgress: Fiber, - capturedUpdate: Update, -) { - // Captured updates are updates that are thrown by a child during the render - // phase. They should be discarded if the render is aborted. Therefore, - // we should only put them on the work-in-progress queue, not the current one. - let queue: UpdateQueue = (workInProgress.updateQueue: any); - - // Check if the work-in-progress queue is a clone. - const current = workInProgress.alternate; - if (current !== null) { - const currentQueue: UpdateQueue = (current.updateQueue: any); - if (queue === currentQueue) { - // The work-in-progress queue is the same as current. This happens when - // we bail out on a parent fiber that then captures an error thrown by - // a child. Since we want to append the update only to the work-in - // -progress queue, we need to clone the updates. We usually clone during - // processUpdateQueue, but that didn't happen in this case because we - // skipped over the parent when we bailed out. - let newFirst = null; - let newLast = null; - const firstBaseUpdate = queue.firstBaseUpdate; - if (firstBaseUpdate !== null) { - // Loop through the updates and clone them. - let update: Update = firstBaseUpdate; - do { - const clone: Update = { - eventTime: update.eventTime, - lane: update.lane, - - tag: update.tag, - payload: update.payload, - // When this update is rebased, we should not fire its - // callback again. - callback: null, - - next: null, - }; - if (newLast === null) { - newFirst = newLast = clone; - } else { - newLast.next = clone; - newLast = clone; - } - // $FlowFixMe[incompatible-type] we bail out when we get a null - update = update.next; - } while (update !== null); - - // Append the captured update the end of the cloned list. - if (newLast === null) { - newFirst = newLast = capturedUpdate; - } else { - newLast.next = capturedUpdate; - newLast = capturedUpdate; - } - } else { - // There are no base updates. - newFirst = newLast = capturedUpdate; - } - queue = { - baseState: currentQueue.baseState, - firstBaseUpdate: newFirst, - lastBaseUpdate: newLast, - shared: currentQueue.shared, - callbacks: currentQueue.callbacks, - }; - workInProgress.updateQueue = queue; - return; - } - } - - // Append the update to the end of the list. - const lastBaseUpdate = queue.lastBaseUpdate; - if (lastBaseUpdate === null) { - queue.firstBaseUpdate = capturedUpdate; - } else { - lastBaseUpdate.next = capturedUpdate; - } - queue.lastBaseUpdate = capturedUpdate; -} - -function getStateFromUpdate( - workInProgress: Fiber, - queue: UpdateQueue, - update: Update, - prevState: State, - nextProps: any, - instance: any, -): any { - switch (update.tag) { - case ReplaceState: { - const payload = update.payload; - if (typeof payload === 'function') { - // Updater function - if (__DEV__) { - enterDisallowedContextReadInDEV(); - } - const nextState = payload.call(instance, prevState, nextProps); - if (__DEV__) { - if ( - debugRenderPhaseSideEffectsForStrictMode && - workInProgress.mode & StrictLegacyMode - ) { - setIsStrictModeForDevtools(true); - try { - payload.call(instance, prevState, nextProps); - } finally { - setIsStrictModeForDevtools(false); - } - } - exitDisallowedContextReadInDEV(); - } - return nextState; - } - // State object - return payload; - } - case CaptureUpdate: { - workInProgress.flags = - (workInProgress.flags & ~ShouldCapture) | DidCapture; - } - // Intentional fallthrough - case UpdateState: { - const payload = update.payload; - let partialState; - if (typeof payload === 'function') { - // Updater function - if (__DEV__) { - enterDisallowedContextReadInDEV(); - } - partialState = payload.call(instance, prevState, nextProps); - if (__DEV__) { - if ( - debugRenderPhaseSideEffectsForStrictMode && - workInProgress.mode & StrictLegacyMode - ) { - setIsStrictModeForDevtools(true); - try { - payload.call(instance, prevState, nextProps); - } finally { - setIsStrictModeForDevtools(false); - } - } - exitDisallowedContextReadInDEV(); - } - } else { - // Partial state object - partialState = payload; - } - if (partialState === null || partialState === undefined) { - // Null and undefined are treated as no-ops. - return prevState; - } - // Merge the partial state and the previous state. - return assign({}, prevState, partialState); - } - case ForceUpdate: { - hasForceUpdate = true; - return prevState; - } - } - return prevState; -} - -export function processUpdateQueue( - workInProgress: Fiber, - props: any, - instance: any, - renderLanes: Lanes, -): void { - // This is always non-null on a ClassComponent or HostRoot - const queue: UpdateQueue = (workInProgress.updateQueue: any); - - hasForceUpdate = false; - - if (__DEV__) { - // $FlowFixMe[escaped-generic] discovered when updating Flow - currentlyProcessingQueue = queue.shared; - } - - let firstBaseUpdate = queue.firstBaseUpdate; - let lastBaseUpdate = queue.lastBaseUpdate; - - // Check if there are pending updates. If so, transfer them to the base queue. - let pendingQueue = queue.shared.pending; - if (pendingQueue !== null) { - queue.shared.pending = null; - - // The pending queue is circular. Disconnect the pointer between first - // and last so that it's non-circular. - const lastPendingUpdate = pendingQueue; - const firstPendingUpdate = lastPendingUpdate.next; - lastPendingUpdate.next = null; - // Append pending updates to base queue - if (lastBaseUpdate === null) { - firstBaseUpdate = firstPendingUpdate; - } else { - lastBaseUpdate.next = firstPendingUpdate; - } - lastBaseUpdate = lastPendingUpdate; - - // If there's a current queue, and it's different from the base queue, then - // we need to transfer the updates to that queue, too. Because the base - // queue is a singly-linked list with no cycles, we can append to both - // lists and take advantage of structural sharing. - // TODO: Pass `current` as argument - const current = workInProgress.alternate; - if (current !== null) { - // This is always non-null on a ClassComponent or HostRoot - const currentQueue: UpdateQueue = (current.updateQueue: any); - const currentLastBaseUpdate = currentQueue.lastBaseUpdate; - if (currentLastBaseUpdate !== lastBaseUpdate) { - if (currentLastBaseUpdate === null) { - currentQueue.firstBaseUpdate = firstPendingUpdate; - } else { - currentLastBaseUpdate.next = firstPendingUpdate; - } - currentQueue.lastBaseUpdate = lastPendingUpdate; - } - } - } - - // These values may change as we process the queue. - if (firstBaseUpdate !== null) { - // Iterate through the list of updates to compute the result. - let newState = queue.baseState; - // TODO: Don't need to accumulate this. Instead, we can remove renderLanes - // from the original lanes. - let newLanes = NoLanes; - - let newBaseState = null; - let newFirstBaseUpdate = null; - let newLastBaseUpdate = null; - - let update: Update = firstBaseUpdate; - do { - // TODO: Don't need this field anymore - const updateEventTime = update.eventTime; - - // An extra OffscreenLane bit is added to updates that were made to - // a hidden tree, so that we can distinguish them from updates that were - // already there when the tree was hidden. - const updateLane = removeLanes(update.lane, OffscreenLane); - const isHiddenUpdate = updateLane !== update.lane; - - // Check if this update was made while the tree was hidden. If so, then - // it's not a "base" update and we should disregard the extra base lanes - // that were added to renderLanes when we entered the Offscreen tree. - const shouldSkipUpdate = isHiddenUpdate - ? !isSubsetOfLanes(getWorkInProgressRootRenderLanes(), updateLane) - : !isSubsetOfLanes(renderLanes, updateLane); - - if (shouldSkipUpdate) { - // Priority is insufficient. Skip this update. If this is the first - // skipped update, the previous update/state is the new base - // update/state. - const clone: Update = { - eventTime: updateEventTime, - lane: updateLane, - - tag: update.tag, - payload: update.payload, - callback: update.callback, - - next: null, - }; - if (newLastBaseUpdate === null) { - newFirstBaseUpdate = newLastBaseUpdate = clone; - newBaseState = newState; - } else { - newLastBaseUpdate = newLastBaseUpdate.next = clone; - } - // Update the remaining priority in the queue. - newLanes = mergeLanes(newLanes, updateLane); - } else { - // This update does have sufficient priority. - - if (newLastBaseUpdate !== null) { - const clone: Update = { - eventTime: updateEventTime, - // This update is going to be committed so we never want uncommit - // it. Using NoLane works because 0 is a subset of all bitmasks, so - // this will never be skipped by the check above. - lane: NoLane, - - tag: update.tag, - payload: update.payload, - - // When this update is rebased, we should not fire its - // callback again. - callback: null, - - next: null, - }; - newLastBaseUpdate = newLastBaseUpdate.next = clone; - } - - // Process this update. - newState = getStateFromUpdate( - workInProgress, - queue, - update, - newState, - props, - instance, - ); - const callback = update.callback; - if (callback !== null) { - workInProgress.flags |= Callback; - if (isHiddenUpdate) { - workInProgress.flags |= Visibility; - } - const callbacks = queue.callbacks; - if (callbacks === null) { - queue.callbacks = [callback]; - } else { - callbacks.push(callback); - } - } - } - // $FlowFixMe[incompatible-type] we bail out when we get a null - update = update.next; - if (update === null) { - pendingQueue = queue.shared.pending; - if (pendingQueue === null) { - break; - } else { - // An update was scheduled from inside a reducer. Add the new - // pending updates to the end of the list and keep processing. - const lastPendingUpdate = pendingQueue; - // Intentionally unsound. Pending updates form a circular list, but we - // unravel them when transferring them to the base queue. - const firstPendingUpdate = ((lastPendingUpdate.next: any): Update); - lastPendingUpdate.next = null; - update = firstPendingUpdate; - queue.lastBaseUpdate = lastPendingUpdate; - queue.shared.pending = null; - } - } - } while (true); - - if (newLastBaseUpdate === null) { - newBaseState = newState; - } - - queue.baseState = ((newBaseState: any): State); - queue.firstBaseUpdate = newFirstBaseUpdate; - queue.lastBaseUpdate = newLastBaseUpdate; - - if (firstBaseUpdate === null) { - // `queue.lanes` is used for entangling transitions. We can set it back to - // zero once the queue is empty. - queue.shared.lanes = NoLanes; - } - - // Set the remaining expiration time to be whatever is remaining in the queue. - // This should be fine because the only two other things that contribute to - // expiration time are props and context. We're already in the middle of the - // begin phase by the time we start processing the queue, so we've already - // dealt with the props. Context in components that specify - // shouldComponentUpdate is tricky; but we'll have to account for - // that regardless. - markSkippedUpdateLanes(newLanes); - workInProgress.lanes = newLanes; - workInProgress.memoizedState = newState; - } - - if (__DEV__) { - currentlyProcessingQueue = null; - } -} - -function callCallback(callback, context) { - if (typeof callback !== 'function') { - throw new Error( - 'Invalid argument passed as callback. Expected a function. Instead ' + - `received: ${callback}`, - ); - } - - callback.call(context); -} - -export function resetHasForceUpdateBeforeProcessing() { - hasForceUpdate = false; -} - -export function checkHasForceUpdateAfterProcessing(): boolean { - return hasForceUpdate; -} - -export function deferHiddenCallbacks( - updateQueue: UpdateQueue, -): void { - // When an update finishes on a hidden component, its callback should not - // be fired until/unless the component is made visible again. Stash the - // callback on the shared queue object so it can be fired later. - const newHiddenCallbacks = updateQueue.callbacks; - if (newHiddenCallbacks !== null) { - const existingHiddenCallbacks = updateQueue.shared.hiddenCallbacks; - if (existingHiddenCallbacks === null) { - updateQueue.shared.hiddenCallbacks = newHiddenCallbacks; - } else { - updateQueue.shared.hiddenCallbacks = existingHiddenCallbacks.concat( - newHiddenCallbacks, - ); - } - } -} - -export function commitHiddenCallbacks( - updateQueue: UpdateQueue, - context: any, -): void { - // This component is switching from hidden -> visible. Commit any callbacks - // that were previously deferred. - const hiddenCallbacks = updateQueue.shared.hiddenCallbacks; - if (hiddenCallbacks !== null) { - updateQueue.shared.hiddenCallbacks = null; - for (let i = 0; i < hiddenCallbacks.length; i++) { - const callback = hiddenCallbacks[i]; - callCallback(callback, context); - } - } -} - -export function commitCallbacks( - updateQueue: UpdateQueue, - context: any, -): void { - const callbacks = updateQueue.callbacks; - if (callbacks !== null) { - updateQueue.callbacks = null; - for (let i = 0; i < callbacks.length; i++) { - const callback = callbacks[i]; - callCallback(callback, context); - } - } -} From 6b9c1d12c6df2950aba62e9cf6d481a3257e56b6 Mon Sep 17 00:00:00 2001 From: Samuel Susla Date: Fri, 2 Dec 2022 15:41:30 +0000 Subject: [PATCH 3/3] Use relative import --- packages/react-reconciler/src/ReactFiberClassUpdateQueue.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-reconciler/src/ReactFiberClassUpdateQueue.js b/packages/react-reconciler/src/ReactFiberClassUpdateQueue.js index d2806ec7bca81..fa2de881dd59a 100644 --- a/packages/react-reconciler/src/ReactFiberClassUpdateQueue.js +++ b/packages/react-reconciler/src/ReactFiberClassUpdateQueue.js @@ -108,7 +108,7 @@ import { ShouldCapture, DidCapture, } from './ReactFiberFlags'; -import getComponentNameFromFiber from 'react-reconciler/src/getComponentNameFromFiber'; +import getComponentNameFromFiber from './getComponentNameFromFiber'; import {debugRenderPhaseSideEffectsForStrictMode} from 'shared/ReactFeatureFlags';