import type {Fiber} from './ReactInternalTypes';
import type {Lanes} from './ReactFiberLane';
import type {UpdateQueue} from './ReactFiberClassUpdateQueue';
import {
LayoutStatic,
Update,
Snapshot,
MountLayoutDev,
} from './ReactFiberFlags';
import {
disableLegacyContext,
enableSchedulingProfiler,
} from 'shared/ReactFeatureFlags';
import ReactStrictModeWarnings from './ReactStrictModeWarnings';
import {get as getInstance, set as setInstance} from 'shared/ReactInstanceMap';
import shallowEqual from 'shared/shallowEqual';
import getComponentNameFromFiber from 'react-reconciler/src/getComponentNameFromFiber';
import getComponentNameFromType from 'shared/getComponentNameFromType';
import assign from 'shared/assign';
import isArray from 'shared/isArray';
import {REACT_CONTEXT_TYPE, REACT_CONSUMER_TYPE} from 'shared/ReactSymbols';
import {NoMode, StrictLegacyMode, StrictEffectsMode} from './ReactTypeOfMode';
import {
enqueueUpdate,
entangleTransitions,
processUpdateQueue,
checkHasForceUpdateAfterProcessing,
resetHasForceUpdateBeforeProcessing,
createUpdate,
ReplaceState,
ForceUpdate,
initializeUpdateQueue,
cloneUpdateQueue,
suspendIfUpdateReadFromEntangledAsyncAction,
} from './ReactFiberClassUpdateQueue';
import {NoLanes} from './ReactFiberLane';
import {
cacheContext,
getMaskedContext,
getUnmaskedContext,
hasContextChanged,
emptyContextObject,
} from './ReactFiberLegacyContext';
import {readContext, checkIfContextChanged} from './ReactFiberNewContext';
import {requestUpdateLane, scheduleUpdateOnFiber} from './ReactFiberWorkLoop';
import {
markForceUpdateScheduled,
markStateUpdateScheduled,
setIsStrictModeForDevtools,
} from './ReactFiberDevToolsHook';
import {startUpdateTimerByLane} from './ReactProfilerTimer';
const fakeInternalInstance = {};
let didWarnAboutStateAssignmentForComponent;
let didWarnAboutUninitializedState;
let didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate;
let didWarnAboutLegacyLifecyclesAndDerivedState;
let didWarnAboutUndefinedDerivedState;
let didWarnAboutDirectlyAssigningPropsToState;
let didWarnAboutContextTypeAndContextTypes;
let didWarnAboutContextTypes;
let didWarnAboutChildContextTypes;
let didWarnAboutInvalidateContextType;
let didWarnOnInvalidCallback;
if (__DEV__) {
didWarnAboutStateAssignmentForComponent = new Set<string>();
didWarnAboutUninitializedState = new Set<string>();
didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate = new Set<string>();
didWarnAboutLegacyLifecyclesAndDerivedState = new Set<string>();
didWarnAboutDirectlyAssigningPropsToState = new Set<string>();
didWarnAboutUndefinedDerivedState = new Set<string>();
didWarnAboutContextTypeAndContextTypes = new Set<string>();
didWarnAboutContextTypes = new Set<mixed>();
didWarnAboutChildContextTypes = new Set<mixed>();
didWarnAboutInvalidateContextType = new Set<string>();
didWarnOnInvalidCallback = new Set<string>();
Object.freeze(fakeInternalInstance);
}
function warnOnInvalidCallback(callback: mixed) {
if (__DEV__) {
if (callback === null || typeof callback === 'function') {
return;
}
const key = String(callback);
if (!didWarnOnInvalidCallback.has(key)) {
didWarnOnInvalidCallback.add(key);
console.error(
'Expected the last optional `callback` argument to be a ' +
'function. Instead received: %s.',
callback,
);
}
}
}
function warnOnUndefinedDerivedState(type: any, partialState: any) {
if (__DEV__) {
if (partialState === undefined) {
const componentName = getComponentNameFromType(type) || 'Component';
if (!didWarnAboutUndefinedDerivedState.has(componentName)) {
didWarnAboutUndefinedDerivedState.add(componentName);
console.error(
'%s.getDerivedStateFromProps(): A valid state object (or null) must be returned. ' +
'You have returned undefined.',
componentName,
);
}
}
}
}
function applyDerivedStateFromProps(
workInProgress: Fiber,
ctor: any,
getDerivedStateFromProps: (props: any, state: any) => any,
nextProps: any,
) {
const prevState = workInProgress.memoizedState;
let partialState = getDerivedStateFromProps(nextProps, prevState);
if (__DEV__) {
if (workInProgress.mode & StrictLegacyMode) {
setIsStrictModeForDevtools(true);
try {
partialState = getDerivedStateFromProps(nextProps, prevState);
} finally {
setIsStrictModeForDevtools(false);
}
}
warnOnUndefinedDerivedState(ctor, partialState);
}
const memoizedState =
partialState === null || partialState === undefined
? prevState
: assign({}, prevState, partialState);
workInProgress.memoizedState = memoizedState;
if (workInProgress.lanes === NoLanes) {
const updateQueue: UpdateQueue<any> = (workInProgress.updateQueue: any);
updateQueue.baseState = memoizedState;
}
}
const classComponentUpdater = {
enqueueSetState(inst: any, payload: any, callback) {
const fiber = getInstance(inst);
const lane = requestUpdateLane(fiber);
const update = createUpdate(lane);
update.payload = payload;
if (callback !== undefined && callback !== null) {
if (__DEV__) {
warnOnInvalidCallback(callback);
}
update.callback = callback;
}
const root = enqueueUpdate(fiber, update, lane);
if (root !== null) {
startUpdateTimerByLane(lane, 'this.setState()');
scheduleUpdateOnFiber(root, fiber, lane);
entangleTransitions(root, fiber, lane);
}
if (enableSchedulingProfiler) {
markStateUpdateScheduled(fiber, lane);
}
},
enqueueReplaceState(inst: any, payload: any, callback: null) {
const fiber = getInstance(inst);
const lane = requestUpdateLane(fiber);
const update = createUpdate(lane);
update.tag = ReplaceState;
update.payload = payload;
if (callback !== undefined && callback !== null) {
if (__DEV__) {
warnOnInvalidCallback(callback);
}
update.callback = callback;
}
const root = enqueueUpdate(fiber, update, lane);
if (root !== null) {
startUpdateTimerByLane(lane, 'this.replaceState()');
scheduleUpdateOnFiber(root, fiber, lane);
entangleTransitions(root, fiber, lane);
}
if (enableSchedulingProfiler) {
markStateUpdateScheduled(fiber, lane);
}
},
enqueueForceUpdate(inst: any, callback) {
const fiber = getInstance(inst);
const lane = requestUpdateLane(fiber);
const update = createUpdate(lane);
update.tag = ForceUpdate;
if (callback !== undefined && callback !== null) {
if (__DEV__) {
warnOnInvalidCallback(callback);
}
update.callback = callback;
}
const root = enqueueUpdate(fiber, update, lane);
if (root !== null) {
startUpdateTimerByLane(lane, 'this.forceUpdate()');
scheduleUpdateOnFiber(root, fiber, lane);
entangleTransitions(root, fiber, lane);
}
if (enableSchedulingProfiler) {
markForceUpdateScheduled(fiber, lane);
}
},
};
function checkShouldComponentUpdate(
workInProgress: Fiber,
ctor: any,
oldProps: any,
newProps: any,
oldState: any,
newState: any,
nextContext: any,
) {
const instance = workInProgress.stateNode;
if (typeof instance.shouldComponentUpdate === 'function') {
let shouldUpdate = instance.shouldComponentUpdate(
newProps,
newState,
nextContext,
);
if (__DEV__) {
if (workInProgress.mode & StrictLegacyMode) {
setIsStrictModeForDevtools(true);
try {
shouldUpdate = instance.shouldComponentUpdate(
newProps,
newState,
nextContext,
);
} finally {
setIsStrictModeForDevtools(false);
}
}
if (shouldUpdate === undefined) {
console.error(
'%s.shouldComponentUpdate(): Returned undefined instead of a ' +
'boolean value. Make sure to return true or false.',
getComponentNameFromType(ctor) || 'Component',
);
}
}
return shouldUpdate;
}
if (ctor.prototype && ctor.prototype.isPureReactComponent) {
return (
!shallowEqual(oldProps, newProps) || !shallowEqual(oldState, newState)
);
}
return true;
}
function checkClassInstance(workInProgress: Fiber, ctor: any, newProps: any) {
const instance = workInProgress.stateNode;
if (__DEV__) {
const name = getComponentNameFromType(ctor) || 'Component';
const renderPresent = instance.render;
if (!renderPresent) {
if (ctor.prototype && typeof ctor.prototype.render === 'function') {
console.error(
'No `render` method found on the %s ' +
'instance: did you accidentally return an object from the constructor?',
name,
);
} else {
console.error(
'No `render` method found on the %s ' +
'instance: you may have forgotten to define `render`.',
name,
);
}
}
if (
instance.getInitialState &&
!instance.getInitialState.isReactClassApproved &&
!instance.state
) {
console.error(
'getInitialState was defined on %s, a plain JavaScript class. ' +
'This is only supported for classes created using React.createClass. ' +
'Did you mean to define a state property instead?',
name,
);
}
if (
instance.getDefaultProps &&
!instance.getDefaultProps.isReactClassApproved
) {
console.error(
'getDefaultProps was defined on %s, a plain JavaScript class. ' +
'This is only supported for classes created using React.createClass. ' +
'Use a static property to define defaultProps instead.',
name,
);
}
if (instance.contextType) {
console.error(
'contextType was defined as an instance property on %s. Use a static ' +
'property to define contextType instead.',
name,
);
}
if (disableLegacyContext) {
if (ctor.childContextTypes && !didWarnAboutChildContextTypes.has(ctor)) {
didWarnAboutChildContextTypes.add(ctor);
console.error(
'%s uses the legacy childContextTypes API which was removed in React 19. ' +
'Use React.createContext() instead. (https://react.dev/link/legacy-context)',
name,
);
}
if (ctor.contextTypes && !didWarnAboutContextTypes.has(ctor)) {
didWarnAboutContextTypes.add(ctor);
console.error(
'%s uses the legacy contextTypes API which was removed in React 19. ' +
'Use React.createContext() with static contextType instead. ' +
'(https://react.dev/link/legacy-context)',
name,
);
}
} else {
if (instance.contextTypes) {
console.error(
'contextTypes was defined as an instance property on %s. Use a static ' +
'property to define contextTypes instead.',
name,
);
}
if (
ctor.contextType &&
ctor.contextTypes &&
!didWarnAboutContextTypeAndContextTypes.has(ctor)
) {
didWarnAboutContextTypeAndContextTypes.add(ctor);
console.error(
'%s declares both contextTypes and contextType static properties. ' +
'The legacy contextTypes property will be ignored.',
name,
);
}
if (ctor.childContextTypes && !didWarnAboutChildContextTypes.has(ctor)) {
didWarnAboutChildContextTypes.add(ctor);
console.error(
'%s uses the legacy childContextTypes API which will soon be removed. ' +
'Use React.createContext() instead. (https://react.dev/link/legacy-context)',
name,
);
}
if (ctor.contextTypes && !didWarnAboutContextTypes.has(ctor)) {
didWarnAboutContextTypes.add(ctor);
console.error(
'%s uses the legacy contextTypes API which will soon be removed. ' +
'Use React.createContext() with static contextType instead. ' +
'(https://react.dev/link/legacy-context)',
name,
);
}
}
if (typeof instance.componentShouldUpdate === 'function') {
console.error(
'%s has a method called ' +
'componentShouldUpdate(). Did you mean shouldComponentUpdate()? ' +
'The name is phrased as a question because the function is ' +
'expected to return a value.',
name,
);
}
if (
ctor.prototype &&
ctor.prototype.isPureReactComponent &&
typeof instance.shouldComponentUpdate !== 'undefined'
) {
console.error(
'%s has a method called shouldComponentUpdate(). ' +
'shouldComponentUpdate should not be used when extending React.PureComponent. ' +
'Please extend React.Component if shouldComponentUpdate is used.',
getComponentNameFromType(ctor) || 'A pure component',
);
}
if (typeof instance.componentDidUnmount === 'function') {
console.error(
'%s has a method called ' +
'componentDidUnmount(). But there is no such lifecycle method. ' +
'Did you mean componentWillUnmount()?',
name,
);
}
if (typeof instance.componentDidReceiveProps === 'function') {
console.error(
'%s has a method called ' +
'componentDidReceiveProps(). But there is no such lifecycle method. ' +
'If you meant to update the state in response to changing props, ' +
'use componentWillReceiveProps(). If you meant to fetch data or ' +
'run side-effects or mutations after React has updated the UI, use componentDidUpdate().',
name,
);
}
if (typeof instance.componentWillRecieveProps === 'function') {
console.error(
'%s has a method called ' +
'componentWillRecieveProps(). Did you mean componentWillReceiveProps()?',
name,
);
}
if (typeof instance.UNSAFE_componentWillRecieveProps === 'function') {
console.error(
'%s has a method called ' +
'UNSAFE_componentWillRecieveProps(). Did you mean UNSAFE_componentWillReceiveProps()?',
name,
);
}
const hasMutatedProps = instance.props !== newProps;
if (instance.props !== undefined && hasMutatedProps) {
console.error(
'When calling super() in `%s`, make sure to pass ' +
"up the same props that your component's constructor was passed.",
name,
);
}
if (instance.defaultProps) {
console.error(
'Setting defaultProps as an instance property on %s is not supported and will be ignored.' +
' Instead, define defaultProps as a static property on %s.',
name,
name,
);
}
if (
typeof instance.getSnapshotBeforeUpdate === 'function' &&
typeof instance.componentDidUpdate !== 'function' &&
!didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate.has(ctor)
) {
didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate.add(ctor);
console.error(
'%s: getSnapshotBeforeUpdate() should be used with componentDidUpdate(). ' +
'This component defines getSnapshotBeforeUpdate() only.',
getComponentNameFromType(ctor),
);
}
if (typeof instance.getDerivedStateFromProps === 'function') {
console.error(
'%s: getDerivedStateFromProps() is defined as an instance method ' +
'and will be ignored. Instead, declare it as a static method.',
name,
);
}
if (typeof instance.getDerivedStateFromError === 'function') {
console.error(
'%s: getDerivedStateFromError() is defined as an instance method ' +
'and will be ignored. Instead, declare it as a static method.',
name,
);
}
if (typeof ctor.getSnapshotBeforeUpdate === 'function') {
console.error(
'%s: getSnapshotBeforeUpdate() is defined as a static method ' +
'and will be ignored. Instead, declare it as an instance method.',
name,
);
}
const state = instance.state;
if (state && (typeof state !== 'object' || isArray(state))) {
console.error('%s.state: must be set to an object or null', name);
}
if (
typeof instance.getChildContext === 'function' &&
typeof ctor.childContextTypes !== 'object'
) {
console.error(
'%s.getChildContext(): childContextTypes must be defined in order to ' +
'use getChildContext().',
name,
);
}
}
}
function constructClassInstance(
workInProgress: Fiber,
ctor: any,
props: any,
): any {
let isLegacyContextConsumer = false;
let unmaskedContext = emptyContextObject;
let context = emptyContextObject;
const contextType = ctor.contextType;
if (__DEV__) {
if ('contextType' in ctor) {
const isValid =
contextType === null ||
(contextType !== undefined &&
contextType.$$typeof === REACT_CONTEXT_TYPE);
if (!isValid && !didWarnAboutInvalidateContextType.has(ctor)) {
didWarnAboutInvalidateContextType.add(ctor);
let addendum = '';
if (contextType === undefined) {
addendum =
' However, it is set to undefined. ' +
'This can be caused by a typo or by mixing up named and default imports. ' +
'This can also happen due to a circular dependency, so ' +
'try moving the createContext() call to a separate file.';
} else if (typeof contextType !== 'object') {
addendum = ' However, it is set to a ' + typeof contextType + '.';
} else if (contextType.$$typeof === REACT_CONSUMER_TYPE) {
addendum = ' Did you accidentally pass the Context.Consumer instead?';
} else {
addendum =
' However, it is set to an object with keys {' +
Object.keys(contextType).join(', ') +
'}.';
}
console.error(
'%s defines an invalid contextType. ' +
'contextType should point to the Context object returned by React.createContext().%s',
getComponentNameFromType(ctor) || 'Component',
addendum,
);
}
}
}
if (typeof contextType === 'object' && contextType !== null) {
context = readContext((contextType: any));
} else if (!disableLegacyContext) {
unmaskedContext = getUnmaskedContext(workInProgress, ctor, true);
const contextTypes = ctor.contextTypes;
isLegacyContextConsumer =
contextTypes !== null && contextTypes !== undefined;
context = isLegacyContextConsumer
? getMaskedContext(workInProgress, unmaskedContext)
: emptyContextObject;
}
let instance = new ctor(props, context);
if (__DEV__) {
if (workInProgress.mode & StrictLegacyMode) {
setIsStrictModeForDevtools(true);
try {
instance = new ctor(props, context);
} finally {
setIsStrictModeForDevtools(false);
}
}
}
const state = (workInProgress.memoizedState =
instance.state !== null && instance.state !== undefined
? instance.state
: null);
instance.updater = classComponentUpdater;
workInProgress.stateNode = instance;
setInstance(instance, workInProgress);
if (__DEV__) {
instance._reactInternalInstance = fakeInternalInstance;
}
if (__DEV__) {
if (typeof ctor.getDerivedStateFromProps === 'function' && state === null) {
const componentName = getComponentNameFromType(ctor) || 'Component';
if (!didWarnAboutUninitializedState.has(componentName)) {
didWarnAboutUninitializedState.add(componentName);
console.error(
'`%s` uses `getDerivedStateFromProps` but its initial state is ' +
'%s. This is not recommended. Instead, define the initial state by ' +
'assigning an object to `this.state` in the constructor of `%s`. ' +
'This ensures that `getDerivedStateFromProps` arguments have a consistent shape.',
componentName,
instance.state === null ? 'null' : 'undefined',
componentName,
);
}
}
if (
typeof ctor.getDerivedStateFromProps === 'function' ||
typeof instance.getSnapshotBeforeUpdate === 'function'
) {
let foundWillMountName = null;
let foundWillReceivePropsName = null;
let foundWillUpdateName = null;
if (
typeof instance.componentWillMount === 'function' &&
instance.componentWillMount.__suppressDeprecationWarning !== true
) {
foundWillMountName = 'componentWillMount';
} else if (typeof instance.UNSAFE_componentWillMount === 'function') {
foundWillMountName = 'UNSAFE_componentWillMount';
}
if (
typeof instance.componentWillReceiveProps === 'function' &&
instance.componentWillReceiveProps.__suppressDeprecationWarning !== true
) {
foundWillReceivePropsName = 'componentWillReceiveProps';
} else if (
typeof instance.UNSAFE_componentWillReceiveProps === 'function'
) {
foundWillReceivePropsName = 'UNSAFE_componentWillReceiveProps';
}
if (
typeof instance.componentWillUpdate === 'function' &&
instance.componentWillUpdate.__suppressDeprecationWarning !== true
) {
foundWillUpdateName = 'componentWillUpdate';
} else if (typeof instance.UNSAFE_componentWillUpdate === 'function') {
foundWillUpdateName = 'UNSAFE_componentWillUpdate';
}
if (
foundWillMountName !== null ||
foundWillReceivePropsName !== null ||
foundWillUpdateName !== null
) {
const componentName = getComponentNameFromType(ctor) || 'Component';
const newApiName =
typeof ctor.getDerivedStateFromProps === 'function'
? 'getDerivedStateFromProps()'
: 'getSnapshotBeforeUpdate()';
if (!didWarnAboutLegacyLifecyclesAndDerivedState.has(componentName)) {
didWarnAboutLegacyLifecyclesAndDerivedState.add(componentName);
console.error(
'Unsafe legacy lifecycles will not be called for components using new component APIs.\n\n' +
'%s uses %s but also contains the following legacy lifecycles:%s%s%s\n\n' +
'The above lifecycles should be removed. Learn more about this warning here:\n' +
'https://react.dev/link/unsafe-component-lifecycles',
componentName,
newApiName,
foundWillMountName !== null ? `\n ${foundWillMountName}` : '',
foundWillReceivePropsName !== null
? `\n ${foundWillReceivePropsName}`
: '',
foundWillUpdateName !== null ? `\n ${foundWillUpdateName}` : '',
);
}
}
}
}
if (isLegacyContextConsumer) {
cacheContext(workInProgress, unmaskedContext, context);
}
return instance;
}
function callComponentWillMount(workInProgress: Fiber, instance: any) {
const oldState = instance.state;
if (typeof instance.componentWillMount === 'function') {
instance.componentWillMount();
}
if (typeof instance.UNSAFE_componentWillMount === 'function') {
instance.UNSAFE_componentWillMount();
}
if (oldState !== instance.state) {
if (__DEV__) {
console.error(
'%s.componentWillMount(): Assigning directly to this.state is ' +
"deprecated (except inside a component's " +
'constructor). Use setState instead.',
getComponentNameFromFiber(workInProgress) || 'Component',
);
}
classComponentUpdater.enqueueReplaceState(instance, instance.state, null);
}
}
function callComponentWillReceiveProps(
workInProgress: Fiber,
instance: any,
newProps: any,
nextContext: any,
) {
const oldState = instance.state;
if (typeof instance.componentWillReceiveProps === 'function') {
instance.componentWillReceiveProps(newProps, nextContext);
}
if (typeof instance.UNSAFE_componentWillReceiveProps === 'function') {
instance.UNSAFE_componentWillReceiveProps(newProps, nextContext);
}
if (instance.state !== oldState) {
if (__DEV__) {
const componentName =
getComponentNameFromFiber(workInProgress) || 'Component';
if (!didWarnAboutStateAssignmentForComponent.has(componentName)) {
didWarnAboutStateAssignmentForComponent.add(componentName);
console.error(
'%s.componentWillReceiveProps(): Assigning directly to ' +
"this.state is deprecated (except inside a component's " +
'constructor). Use setState instead.',
componentName,
);
}
}
classComponentUpdater.enqueueReplaceState(instance, instance.state, null);
}
}
function mountClassInstance(
workInProgress: Fiber,
ctor: any,
newProps: any,
renderLanes: Lanes,
): void {
if (__DEV__) {
checkClassInstance(workInProgress, ctor, newProps);
}
const instance = workInProgress.stateNode;
instance.props = newProps;
instance.state = workInProgress.memoizedState;
instance.refs = {};
initializeUpdateQueue(workInProgress);
const contextType = ctor.contextType;
if (typeof contextType === 'object' && contextType !== null) {
instance.context = readContext(contextType);
} else if (disableLegacyContext) {
instance.context = emptyContextObject;
} else {
const unmaskedContext = getUnmaskedContext(workInProgress, ctor, true);
instance.context = getMaskedContext(workInProgress, unmaskedContext);
}
if (__DEV__) {
if (instance.state === newProps) {
const componentName = getComponentNameFromType(ctor) || 'Component';
if (!didWarnAboutDirectlyAssigningPropsToState.has(componentName)) {
didWarnAboutDirectlyAssigningPropsToState.add(componentName);
console.error(
'%s: It is not recommended to assign props directly to state ' +
"because updates to props won't be reflected in state. " +
'In most cases, it is better to use props directly.',
componentName,
);
}
}
if (workInProgress.mode & StrictLegacyMode) {
ReactStrictModeWarnings.recordLegacyContextWarning(
workInProgress,
instance,
);
}
ReactStrictModeWarnings.recordUnsafeLifecycleWarnings(
workInProgress,
instance,
);
}
instance.state = workInProgress.memoizedState;
const getDerivedStateFromProps = ctor.getDerivedStateFromProps;
if (typeof getDerivedStateFromProps === 'function') {
applyDerivedStateFromProps(
workInProgress,
ctor,
getDerivedStateFromProps,
newProps,
);
instance.state = workInProgress.memoizedState;
}
if (
typeof ctor.getDerivedStateFromProps !== 'function' &&
typeof instance.getSnapshotBeforeUpdate !== 'function' &&
(typeof instance.UNSAFE_componentWillMount === 'function' ||
typeof instance.componentWillMount === 'function')
) {
callComponentWillMount(workInProgress, instance);
processUpdateQueue(workInProgress, newProps, instance, renderLanes);
suspendIfUpdateReadFromEntangledAsyncAction();
instance.state = workInProgress.memoizedState;
}
if (typeof instance.componentDidMount === 'function') {
workInProgress.flags |= Update | LayoutStatic;
}
if (__DEV__ && (workInProgress.mode & StrictEffectsMode) !== NoMode) {
workInProgress.flags |= MountLayoutDev;
}
}
function resumeMountClassInstance(
workInProgress: Fiber,
ctor: any,
newProps: any,
renderLanes: Lanes,
): boolean {
const instance = workInProgress.stateNode;
const unresolvedOldProps = workInProgress.memoizedProps;
const oldProps = resolveClassComponentProps(ctor, unresolvedOldProps);
instance.props = oldProps;
const oldContext = instance.context;
const contextType = ctor.contextType;
let nextContext = emptyContextObject;
if (typeof contextType === 'object' && contextType !== null) {
nextContext = readContext(contextType);
} else if (!disableLegacyContext) {
const nextLegacyUnmaskedContext = getUnmaskedContext(
workInProgress,
ctor,
true,
);
nextContext = getMaskedContext(workInProgress, nextLegacyUnmaskedContext);
}
const getDerivedStateFromProps = ctor.getDerivedStateFromProps;
const hasNewLifecycles =
typeof getDerivedStateFromProps === 'function' ||
typeof instance.getSnapshotBeforeUpdate === 'function';
const unresolvedNewProps = workInProgress.pendingProps;
const didReceiveNewProps = unresolvedNewProps !== unresolvedOldProps;
if (
!hasNewLifecycles &&
(typeof instance.UNSAFE_componentWillReceiveProps === 'function' ||
typeof instance.componentWillReceiveProps === 'function')
) {
if (didReceiveNewProps || oldContext !== nextContext) {
callComponentWillReceiveProps(
workInProgress,
instance,
newProps,
nextContext,
);
}
}
resetHasForceUpdateBeforeProcessing();
const oldState = workInProgress.memoizedState;
let newState = (instance.state = oldState);
processUpdateQueue(workInProgress, newProps, instance, renderLanes);
suspendIfUpdateReadFromEntangledAsyncAction();
newState = workInProgress.memoizedState;
if (
!didReceiveNewProps &&
oldState === newState &&
!hasContextChanged() &&
!checkHasForceUpdateAfterProcessing()
) {
if (typeof instance.componentDidMount === 'function') {
workInProgress.flags |= Update | LayoutStatic;
}
if (__DEV__ && (workInProgress.mode & StrictEffectsMode) !== NoMode) {
workInProgress.flags |= MountLayoutDev;
}
return false;
}
if (typeof getDerivedStateFromProps === 'function') {
applyDerivedStateFromProps(
workInProgress,
ctor,
getDerivedStateFromProps,
newProps,
);
newState = workInProgress.memoizedState;
}
const shouldUpdate =
checkHasForceUpdateAfterProcessing() ||
checkShouldComponentUpdate(
workInProgress,
ctor,
oldProps,
newProps,
oldState,
newState,
nextContext,
);
if (shouldUpdate) {
if (
!hasNewLifecycles &&
(typeof instance.UNSAFE_componentWillMount === 'function' ||
typeof instance.componentWillMount === 'function')
) {
if (typeof instance.componentWillMount === 'function') {
instance.componentWillMount();
}
if (typeof instance.UNSAFE_componentWillMount === 'function') {
instance.UNSAFE_componentWillMount();
}
}
if (typeof instance.componentDidMount === 'function') {
workInProgress.flags |= Update | LayoutStatic;
}
if (__DEV__ && (workInProgress.mode & StrictEffectsMode) !== NoMode) {
workInProgress.flags |= MountLayoutDev;
}
} else {
if (typeof instance.componentDidMount === 'function') {
workInProgress.flags |= Update | LayoutStatic;
}
if (__DEV__ && (workInProgress.mode & StrictEffectsMode) !== NoMode) {
workInProgress.flags |= MountLayoutDev;
}
workInProgress.memoizedProps = newProps;
workInProgress.memoizedState = newState;
}
instance.props = newProps;
instance.state = newState;
instance.context = nextContext;
return shouldUpdate;
}
function updateClassInstance(
current: Fiber,
workInProgress: Fiber,
ctor: any,
newProps: any,
renderLanes: Lanes,
): boolean {
const instance = workInProgress.stateNode;
cloneUpdateQueue(current, workInProgress);
const unresolvedOldProps = workInProgress.memoizedProps;
const oldProps = resolveClassComponentProps(ctor, unresolvedOldProps);
instance.props = oldProps;
const unresolvedNewProps = workInProgress.pendingProps;
const oldContext = instance.context;
const contextType = ctor.contextType;
let nextContext = emptyContextObject;
if (typeof contextType === 'object' && contextType !== null) {
nextContext = readContext(contextType);
} else if (!disableLegacyContext) {
const nextUnmaskedContext = getUnmaskedContext(workInProgress, ctor, true);
nextContext = getMaskedContext(workInProgress, nextUnmaskedContext);
}
const getDerivedStateFromProps = ctor.getDerivedStateFromProps;
const hasNewLifecycles =
typeof getDerivedStateFromProps === 'function' ||
typeof instance.getSnapshotBeforeUpdate === 'function';
if (
!hasNewLifecycles &&
(typeof instance.UNSAFE_componentWillReceiveProps === 'function' ||
typeof instance.componentWillReceiveProps === 'function')
) {
if (
unresolvedOldProps !== unresolvedNewProps ||
oldContext !== nextContext
) {
callComponentWillReceiveProps(
workInProgress,
instance,
newProps,
nextContext,
);
}
}
resetHasForceUpdateBeforeProcessing();
const oldState = workInProgress.memoizedState;
let newState = (instance.state = oldState);
processUpdateQueue(workInProgress, newProps, instance, renderLanes);
suspendIfUpdateReadFromEntangledAsyncAction();
newState = workInProgress.memoizedState;
if (
unresolvedOldProps === unresolvedNewProps &&
oldState === newState &&
!hasContextChanged() &&
!checkHasForceUpdateAfterProcessing() &&
!(
current !== null &&
current.dependencies !== null &&
checkIfContextChanged(current.dependencies)
)
) {
if (typeof instance.componentDidUpdate === 'function') {
if (
unresolvedOldProps !== current.memoizedProps ||
oldState !== current.memoizedState
) {
workInProgress.flags |= Update;
}
}
if (typeof instance.getSnapshotBeforeUpdate === 'function') {
if (
unresolvedOldProps !== current.memoizedProps ||
oldState !== current.memoizedState
) {
workInProgress.flags |= Snapshot;
}
}
return false;
}
if (typeof getDerivedStateFromProps === 'function') {
applyDerivedStateFromProps(
workInProgress,
ctor,
getDerivedStateFromProps,
newProps,
);
newState = workInProgress.memoizedState;
}
const shouldUpdate =
checkHasForceUpdateAfterProcessing() ||
checkShouldComponentUpdate(
workInProgress,
ctor,
oldProps,
newProps,
oldState,
newState,
nextContext,
) ||
(current !== null &&
current.dependencies !== null &&
checkIfContextChanged(current.dependencies));
if (shouldUpdate) {
if (
!hasNewLifecycles &&
(typeof instance.UNSAFE_componentWillUpdate === 'function' ||
typeof instance.componentWillUpdate === 'function')
) {
if (typeof instance.componentWillUpdate === 'function') {
instance.componentWillUpdate(newProps, newState, nextContext);
}
if (typeof instance.UNSAFE_componentWillUpdate === 'function') {
instance.UNSAFE_componentWillUpdate(newProps, newState, nextContext);
}
}
if (typeof instance.componentDidUpdate === 'function') {
workInProgress.flags |= Update;
}
if (typeof instance.getSnapshotBeforeUpdate === 'function') {
workInProgress.flags |= Snapshot;
}
} else {
if (typeof instance.componentDidUpdate === 'function') {
if (
unresolvedOldProps !== current.memoizedProps ||
oldState !== current.memoizedState
) {
workInProgress.flags |= Update;
}
}
if (typeof instance.getSnapshotBeforeUpdate === 'function') {
if (
unresolvedOldProps !== current.memoizedProps ||
oldState !== current.memoizedState
) {
workInProgress.flags |= Snapshot;
}
}
workInProgress.memoizedProps = newProps;
workInProgress.memoizedState = newState;
}
instance.props = newProps;
instance.state = newState;
instance.context = nextContext;
return shouldUpdate;
}
export function resolveClassComponentProps(
Component: any,
baseProps: Object,
): Object {
let newProps = baseProps;
if ('ref' in baseProps) {
newProps = ({}: any);
for (const propName in baseProps) {
if (propName !== 'ref') {
newProps[propName] = baseProps[propName];
}
}
}
const defaultProps = Component.defaultProps;
if (defaultProps) {
if (newProps === baseProps) {
newProps = assign({}, newProps);
}
for (const propName in defaultProps) {
if (newProps[propName] === undefined) {
newProps[propName] = defaultProps[propName];
}
}
}
return newProps;
}
export {
constructClassInstance,
mountClassInstance,
resumeMountClassInstance,
updateClassInstance,
};