函数式组件,在一开始创建Fiber的时候,并没有指定类型,是一个不确定类型的组件,在初次渲染的时候,调用的就是mountIndeterminateComponent.为什么函数式组件要这么处理呢? 因为函数式组件可以返回一个带有render函数的对象。这样的对象,可以被认为是class组件,会当做class组件渲染
typescript
function mountIndeterminateComponent(
_current,
workInProgress,
Component,
renderExpirationTime,
) {
let value;
if (__DEV__) {
// ...
} else {
// 调用函数式组件,处理hooks
value = renderWithHooks(
null,
workInProgress,
Component,
props,
context,
renderExpirationTime,
);
}
// React DevTools reads this flag.
workInProgress.effectTag |= PerformedWork;
if (
typeof value === 'object' &&
value !== null &&
typeof value.render === 'function' &&
value.$$typeof === undefined
) {
// 这个判断是什么意思呢 函数式组件如果返回的是对象,并且带有render函数
// 那么当前函数会当成class组件渲染
// function Comp() {
// return {
// render() {
// return <div>111</div>
// }
// }
// }
// Proceed under the assumption that this is a class instance
workInProgress.tag = ClassComponent;
// Throw out any hooks that were used.
resetHooks();
// Push context providers early to prevent context stack mismatches.
// During mounting we don't know the child context yet as the instance doesn't exist.
// We will invalidate the child context in finishClassComponent() right after rendering.
let hasContext = false;
if (isLegacyContextProvider(Component)) {
hasContext = true;
pushLegacyContextProvider(workInProgress);
} else {
hasContext = false;
}
workInProgress.memoizedState =
value.state !== null && value.state !== undefined ? value.state : null;
const getDerivedStateFromProps = Component.getDerivedStateFromProps;
if (typeof getDerivedStateFromProps === 'function') {
applyDerivedStateFromProps(
workInProgress,
Component,
getDerivedStateFromProps,
props,
);
}
adoptClassInstance(workInProgress, value);
mountClassInstance(workInProgress, Component, props, renderExpirationTime);
return finishClassComponent(
null,
workInProgress,
Component,
true,
hasContext,
renderExpirationTime,
);
} else {
workInProgress.tag = FunctionComponent;
// 是函数式组件的话,直接调和子节点,生产子节点的Fiber
reconcileChildren(null, workInProgress, value, renderExpirationTime);
return workInProgress.child;
}
}