worKTags用于标识当前的fiber。

  1. //packages\shared\ReactWorkTags.js
  2. export const FunctionComponent = 0;
  3. export const ClassComponent = 1;
  4. export const IndeterminateComponent = 2; // Before we know whether it is function or class
  5. export const HostRoot = 3; // Root of a host tree. Could be nested inside another node.
  6. export const HostPortal = 4; // A subtree. Could be an entry point to a different renderer.
  7. export const HostComponent = 5;
  8. export const HostText = 6;
  9. export const Fragment = 7;
  10. export const Mode = 8;
  11. export const ContextConsumer = 9;
  12. export const ContextProvider = 10;
  13. export const ForwardRef = 11;
  14. export const Profiler = 12;
  15. export const SuspenseComponent = 13;
  16. export const MemoComponent = 14;
  17. export const SimpleMemoComponent = 15;
  18. export const LazyComponent = 16;
  19. export const IncompleteClassComponent = 17;

createFiberFromElement

workLoop中会创建React Tree,常用的创建createFiberFromElement。

  1. export function createFiberFromElement(
  2. element: ReactElement,
  3. mode: TypeOfMode,
  4. expirationTime: ExpirationTime,
  5. ): Fiber {
  6. let owner = null;
  7. if (__DEV__) {
  8. owner = element._owner;
  9. }
  10. const type = element.type;
  11. const key = element.key;
  12. const pendingProps = element.props;
  13. const fiber = createFiberFromTypeAndProps(
  14. type,
  15. key,
  16. pendingProps,
  17. owner,
  18. mode,
  19. expirationTime,
  20. );
  21. if (__DEV__) {
  22. fiber._debugSource = element._source;
  23. fiber._debugOwner = element._owner;
  24. }
  25. return fiber;
  26. }

此处的element为ReactElement,使用 createFiberFromTypeAndProps 创建fiber时会根据ReactElement的type,赋予不同的fiberTag。

  1. export function createFiberFromTypeAndProps(
  2. type: any, // React$ElementType
  3. key: null | string,
  4. pendingProps: any,
  5. owner: null | Fiber,
  6. mode: TypeOfMode,
  7. expirationTime: ExpirationTime,
  8. ): Fiber {
  9. let fiber;
  10. let fiberTag = IndeterminateComponent;
  11. // The resolved type is set if we know what the final type will be. I.e. it's not lazy.
  12. let resolvedType = type;
  13. if (typeof type === 'function') {
  14. if (shouldConstruct(type)) {
  15. fiberTag = ClassComponent;
  16. }
  17. } else if (typeof type === 'string') {
  18. fiberTag = HostComponent;
  19. } else {
  20. getTag: switch (type) {
  21. case REACT_FRAGMENT_TYPE:
  22. return createFiberFromFragment(
  23. pendingProps.children,
  24. mode,
  25. expirationTime,
  26. key,
  27. );
  28. case REACT_CONCURRENT_MODE_TYPE:
  29. return createFiberFromMode(
  30. pendingProps,
  31. mode | ConcurrentMode | StrictMode,
  32. expirationTime,
  33. key,
  34. );
  35. case REACT_STRICT_MODE_TYPE:
  36. return createFiberFromMode(
  37. pendingProps,
  38. mode | StrictMode,
  39. expirationTime,
  40. key,
  41. );
  42. case REACT_PROFILER_TYPE:
  43. return createFiberFromProfiler(pendingProps, mode, expirationTime, key);
  44. case REACT_SUSPENSE_TYPE:
  45. return createFiberFromSuspense(pendingProps, mode, expirationTime, key);
  46. default: {
  47. if (typeof type === 'object' && type !== null) {
  48. switch (type.$$typeof) {
  49. case REACT_PROVIDER_TYPE:
  50. fiberTag = ContextProvider;
  51. break getTag;
  52. case REACT_CONTEXT_TYPE:
  53. // This is a consumer
  54. fiberTag = ContextConsumer;
  55. break getTag;
  56. case REACT_FORWARD_REF_TYPE:
  57. fiberTag = ForwardRef;
  58. break getTag;
  59. case REACT_MEMO_TYPE:
  60. fiberTag = MemoComponent;
  61. break getTag;
  62. case REACT_LAZY_TYPE:
  63. fiberTag = LazyComponent;
  64. resolvedType = null;
  65. break getTag;
  66. }
  67. }
  68. }
  69. }
  70. }
  71. fiber = createFiber(fiberTag, pendingProps, key, mode);
  72. fiber.elementType = type;
  73. fiber.type = resolvedType;
  74. fiber.expirationTime = expirationTime;
  75. return fiber;
  76. }

IndeterminateComponent

根据ReactElement的type定fiber 的tag。此处function需要注意,若是type是function,不是ClassComponent,则为IndeterminateComponent 。

  1. if (typeof type === 'function') {
  2. if (shouldConstruct(type)) {
  3. fiberTag = ClassComponent;
  4. }
  5. }

HostComponent

字符串类型的’span’、’div’、’p’等,都为 HostComponent。当reconciler 遇到 host element时,它让 renderer 负责挂载它。

Fragment

React还提供了一个组件,可以在不使用包装器的情况下呈现多个元素。

  1. render() {
  2. return (
  3. <React.Fragment>
  4. Some text.
  5. <h2>A heading</h2>
  6. </React.Fragment>
  7. );
  8. }

还可以使用<></>语法。

ContextConsumer

ContextConsumer 是Context.Consumer。

ContextProvider

ContextProvider 是 Context.Provider。

ForwardRef

React.forwardRef
ref的几个缺点

Profiler

一个性能检测工具。

如果这样写,在加载期间,我们必须显示一些内容,例如loading组件,这时就需要使用Suspense component。改写后的例子:

  1. const OtherComponent = React.lazy(() => import('./OtherComponent'));
  2. function MyComponent() {
  3. return (
  4. <div>
  5. <Suspense fallback={<div>Loading...</div>}>
  6. <OtherComponent />
  7. </Suspense>
  8. </div>
  9. );
  10. }

当然也可以在Suspense 中包含多个异步加载的组件,例如:

  1. const OtherComponent = React.lazy(() => import('./OtherComponent'));
  2. const AnotherComponent = React.lazy(() => import('./AnotherComponent'));
  3. function MyComponent() {
  4. return (
  5. <div>
  6. <Suspense fallback={<div>Loading...</div>}>
  7. <section>
  8. <OtherComponent />
  9. <AnotherComponent />
  10. </section>
  11. </Suspense>
  12. </div>
  13. );
  14. }

MemoComponent、SimpleMemoComponent

React.memo 是一个高阶组件。它类似于React.PureComponent,但用于函数组件而不是类。

  1. const MyComponent = React.memo(function MyComponent(props) {
  2. /* render using props */
  3. });

如果你的函数组件在给定相同的道具的情况下呈现相同的结果,则可以React.memo通过记忆结果将其包装在一些调用中以提高性能。这意味着React将跳过渲染组件,并重用最后渲染的结果。

默认情况下,它只会浅显比较props对象中的复杂对象。如果要控制比较,还可以提供自定义比较函数作为第二个参数。

  1. function MyComponent(props) {
  2. /* render using props */
  3. }
  4. function areEqual(prevProps, nextProps) {
  5. /*
  6. return true if passing nextProps to render would return
  7. the same result as passing prevProps to render,
  8. otherwise return false
  9. */
  10. }
  11. export default React.memo(MyComponent, areEqual);

LazyComponent

React.lazy

注意::React.lazy and Suspense 暂时不支持服务端渲染。 React.lazy可以将动态导入呈现为常规组件。