React16源码: React中的updateClassComponent的源码实现
function constructClassInstance(
workInProgress: Fiber,
ctor: any,
props: any,
renderExpirationTime: ExpirationTime,
): any {
// 先跳过 context 相关
let isLegacyContextConsumer = false;
let unmaskedContext = emptyContextObject;
let context = null;
const contextType = ctor.contextType;
//
if (typeof contextType === 'object' && contextType !== null) {
// 跳过 DEV
if (__DEV__) {
if (
contextType.$$typeof !== REACT_CONTEXT_TYPE &&
!didWarnAboutInvalidateContextType.has(ctor)
) {
didWarnAboutInvalidateContextType.add(ctor);
warningWithoutStack(
false,
'%s defines an invalid contextType. ' +
'contextType should point to the Context object returned by React.createContext(). ' +
'Did you accidentally pass the Context.Provider instead?',
getComponentName(ctor) || 'Component',
);
}
}
context = readContext((contextType: any));
} else {
unmaskedContext = getUnmaskedContext(workInProgress, ctor, true);
const contextTypes = ctor.contextTypes;
isLegacyContextConsumer =
contextTypes !== null && contextTypes !== undefined;
context = isLegacyContextConsumer
? getMaskedContext(workInProgress, unmaskedContext)
: emptyContextObject;
}
// Instantiate twice to help detect side-effects.
if (__DEV__) {
if (
debugRenderPhaseSideEffects ||
(debugRenderPhaseSideEffectsForStrictMode &&
workInProgress.mode & StrictMode)
) {
new ctor(props, context); // eslint-disable-line no-new
}
}
// ctor 是 construct 的一个缩写 这个 ctor 就是在 ReactElement当中
// 存在的那个type,也就是 class component 定义的那个class
// 传入 props和context,对应于 ReactBaseClasses.js 里面,Component 函数 接收的这两个参数
// 第三个参数 updater 后面在 adoptClassInstance 里面设置
const instance = new ctor(props, context);
// 获取 state
const state = (workInProgress.memoizedState =
instance.state !== null && instance.state !== undefined
? instance.state
: null);
adoptClassInstance(workInProgress, instance);
if (__DEV__) {
if (typeof ctor.getDerivedStateFromProps === 'function' && state === null) {
const componentName = getComponentName(ctor) || 'Component';
if (!didWarnAboutUninitializedState.has(componentName)) {
didWarnAboutUninitializedState.add(componentName);
warningWithoutStack(
false,
'`%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 new component APIs are defined, "unsafe" lifecycles won't be called.
// Warn about these lifecycles if they are present.
// Don't warn about react-lifecycles-compat polyfilled methods though.
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 = getComponentName(ctor) || 'Component';
const newApiName =
typeof ctor.getDerivedStateFromProps === 'function'
? 'getDerivedStateFromProps()'
: 'getSnapshotBeforeUpdate()';
if (!didWarnAboutLegacyLifecyclesAndDerivedState.has(componentName)) {
didWarnAboutLegacyLifecyclesAndDerivedState.add(componentName);
warningWithoutStack(
false,
'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://fb.me/react-async-component-lifecycle-hooks',
componentName,
newApiName,
foundWillMountName !== null ? `\n ${foundWillMountName}` : '',
foundWillReceivePropsName !== null
? `\n ${foundWillReceivePropsName}`
: '',
foundWillUpdateName !== null ? `\n ${foundWillUpdateName}` : '',
);
}
}
}
}
// Cache unmasked context so we can avoid recreating masked context unless necessary.
// ReactFiberContext usually updates this cache but can't for newly-created instances.
if (isLegacyContextConsumer) {
cacheContext(workInProgress, unmaskedContext, context);
}
return instance;
}