worKTags用于标识当前的fiber。
//packages\shared\ReactWorkTags.jsexport const FunctionComponent = 0;export const ClassComponent = 1;export const IndeterminateComponent = 2; // Before we know whether it is function or classexport const HostRoot = 3; // Root of a host tree. Could be nested inside another node.export const HostPortal = 4; // A subtree. Could be an entry point to a different renderer.export const HostComponent = 5;export const HostText = 6;export const Fragment = 7;export const Mode = 8;export const ContextConsumer = 9;export const ContextProvider = 10;export const ForwardRef = 11;export const Profiler = 12;export const SuspenseComponent = 13;export const MemoComponent = 14;export const SimpleMemoComponent = 15;export const LazyComponent = 16;export const IncompleteClassComponent = 17;
createFiberFromElement
workLoop中会创建React Tree,常用的创建createFiberFromElement。
export function createFiberFromElement(element: ReactElement,mode: TypeOfMode,expirationTime: ExpirationTime,): Fiber {let owner = null;if (__DEV__) {owner = element._owner;}const type = element.type;const key = element.key;const pendingProps = element.props;const fiber = createFiberFromTypeAndProps(type,key,pendingProps,owner,mode,expirationTime,);if (__DEV__) {fiber._debugSource = element._source;fiber._debugOwner = element._owner;}return fiber;}
此处的element为ReactElement,使用 createFiberFromTypeAndProps 创建fiber时会根据ReactElement的type,赋予不同的fiberTag。
export function createFiberFromTypeAndProps(type: any, // React$ElementTypekey: null | string,pendingProps: any,owner: null | Fiber,mode: TypeOfMode,expirationTime: ExpirationTime,): Fiber {let fiber;let fiberTag = IndeterminateComponent;// The resolved type is set if we know what the final type will be. I.e. it's not lazy.let resolvedType = type;if (typeof type === 'function') {if (shouldConstruct(type)) {fiberTag = ClassComponent;}} else if (typeof type === 'string') {fiberTag = HostComponent;} else {getTag: switch (type) {case REACT_FRAGMENT_TYPE:return createFiberFromFragment(pendingProps.children,mode,expirationTime,key,);case REACT_CONCURRENT_MODE_TYPE:return createFiberFromMode(pendingProps,mode | ConcurrentMode | StrictMode,expirationTime,key,);case REACT_STRICT_MODE_TYPE:return createFiberFromMode(pendingProps,mode | StrictMode,expirationTime,key,);case REACT_PROFILER_TYPE:return createFiberFromProfiler(pendingProps, mode, expirationTime, key);case REACT_SUSPENSE_TYPE:return createFiberFromSuspense(pendingProps, mode, expirationTime, key);default: {if (typeof type === 'object' && type !== null) {switch (type.$$typeof) {case REACT_PROVIDER_TYPE:fiberTag = ContextProvider;break getTag;case REACT_CONTEXT_TYPE:// This is a consumerfiberTag = ContextConsumer;break getTag;case REACT_FORWARD_REF_TYPE:fiberTag = ForwardRef;break getTag;case REACT_MEMO_TYPE:fiberTag = MemoComponent;break getTag;case REACT_LAZY_TYPE:fiberTag = LazyComponent;resolvedType = null;break getTag;}}}}}fiber = createFiber(fiberTag, pendingProps, key, mode);fiber.elementType = type;fiber.type = resolvedType;fiber.expirationTime = expirationTime;return fiber;}
IndeterminateComponent
根据ReactElement的type定fiber 的tag。此处function需要注意,若是type是function,不是ClassComponent,则为IndeterminateComponent 。
if (typeof type === 'function') {if (shouldConstruct(type)) {fiberTag = ClassComponent;}}
HostComponent
字符串类型的’span’、’div’、’p’等,都为 HostComponent。当reconciler 遇到 host element时,它让 renderer 负责挂载它。
Fragment
React还提供了一个组件,可以在不使用包装器的情况下呈现多个元素。
render() {return (<React.Fragment>Some text.<h2>A heading</h2></React.Fragment>);}
ContextConsumer
ContextConsumer 是Context.Consumer。
ContextProvider
ContextProvider 是 Context.Provider。
ForwardRef
Profiler
一个性能检测工具。
- with-the-devtools-profiler
- introducing-the-react-profiler
SuspenseComponent
React增加React.lazy之后,可以异步加载组件。例如:const OtherComponent = React.lazy(() => import('./OtherComponent'));function MyComponent() {return (<div><OtherComponent /></div>);}
如果这样写,在加载期间,我们必须显示一些内容,例如loading组件,这时就需要使用Suspense component。改写后的例子:
const OtherComponent = React.lazy(() => import('./OtherComponent'));function MyComponent() {return (<div><Suspense fallback={<div>Loading...</div>}><OtherComponent /></Suspense></div>);}
当然也可以在Suspense 中包含多个异步加载的组件,例如:
const OtherComponent = React.lazy(() => import('./OtherComponent'));const AnotherComponent = React.lazy(() => import('./AnotherComponent'));function MyComponent() {return (<div><Suspense fallback={<div>Loading...</div>}><section><OtherComponent /><AnotherComponent /></section></Suspense></div>);}
MemoComponent、SimpleMemoComponent
React.memo 是一个高阶组件。它类似于React.PureComponent,但用于函数组件而不是类。
const MyComponent = React.memo(function MyComponent(props) {/* render using props */});
如果你的函数组件在给定相同的道具的情况下呈现相同的结果,则可以React.memo通过记忆结果将其包装在一些调用中以提高性能。这意味着React将跳过渲染组件,并重用最后渲染的结果。
默认情况下,它只会浅显比较props对象中的复杂对象。如果要控制比较,还可以提供自定义比较函数作为第二个参数。
function MyComponent(props) {/* render using props */}function areEqual(prevProps, nextProps) {/*return true if passing nextProps to render would returnthe same result as passing prevProps to render,otherwise return false*/}export default React.memo(MyComponent, areEqual);
LazyComponent
注意::React.lazy and Suspense 暂时不支持服务端渲染。 React.lazy可以将动态导入呈现为常规组件。
