React package directory

1.React.js is the API that can be used outside the portal

/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */
// React/React.js
import ReactVersion from 'shared/ReactVersion';
import {
  REACT_CONCURRENT_MODE_TYPE,
  REACT_FRAGMENT_TYPE,
  REACT_PROFILER_TYPE,
  REACT_STRICT_MODE_TYPE,
  REACT_SUSPENSE_TYPE,
} from 'shared/ReactSymbols';

import {Component, PureComponent} from './ReactBaseClasses';
import {createRef} from './ReactCreateRef';
import {forEach, map, count, toArray, only} from './ReactChildren';
import {
  createElement,
  createFactory,
  cloneElement,
  isValidElement,
} from './ReactElement';
import {createContext} from './ReactContext';
import {lazy} from './ReactLazy';
import forwardRef from './forwardRef';
import memo from './memo';
import {
  createElementWithValidation,
  createFactoryWithValidation,
  cloneElementWithValidation,
} from './ReactElementValidator';
import ReactSharedInternals from './ReactSharedInternals';
import {enableStableConcurrentModeAPIs} from 'shared/ReactFeatureFlags';

const React = {
  Children: {
    map,
    forEach,
    count,
    toArray,
    only,
  },

  createRef,
  Component,
  PureComponent,

  createContext,
  forwardRef,
  lazy,
  memo,
	// Native components
  Fragment: REACT_FRAGMENT_TYPE,
  StrictMode: REACT_STRICT_MODE_TYPE,
  Suspense: REACT_SUSPENSE_TYPE,

  createElement: __DEV__ ? createElementWithValidation : createElement,
  cloneElement: __DEV__ ? cloneElementWithValidation : cloneElement,
  createFactory: __DEV__ ? createFactoryWithValidation : createFactory,
  isValidElement: isValidElement,

  version: ReactVersion,

  __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: ReactSharedInternals,
};

if (enableStableConcurrentModeAPIs) {
  React.ConcurrentMode = REACT_CONCURRENT_MODE_TYPE;
  React.Profiler = REACT_PROFILER_TYPE;
} else {
  React.unstable_ConcurrentMode = REACT_CONCURRENT_MODE_TYPE;
  React.unstable_Profiler = REACT_PROFILER_TYPE;
}

export default React;
Copy the code

2.ReactElement.js

// React/ReactElement.js
const ReactElement = function(type, key, ref, self, source, owner, props) {
  const element = {
    // This tag allows us to uniquely identify this as a React Element
    $$typeof: REACT_ELEMENT_TYPE, / /! CreateProtol the $$typeof of React is _protolType_

    // Built-in properties that belong on the element
    type: type, / /! The type of element passed in
    key: key,
    ref: ref,
    props: props,

    // Record the component responsible for creating this element.
    _owner: owner,
  };
  return element
 }
Copy the code
//React/ReactElement.js
export function createElement(type, config, children) {
  let propName;

  // Reserved names are extracted
  const props = {};

  let key = null;
  let ref = null;
  let self = null;
  let source = null;
  / /! Let's see if there's a reasonable ref and key
  if(config ! =null) {
    if (hasValidRef(config)) {
      ref = config.ref;
    }
    if (hasValidKey(config)) {
      key = ' ' + config.key;
    }

    self = config.__self === undefined ? null : config.__self;
    source = config.__source === undefined ? null : config.__source;
    // Remaining properties are added to a new props object
    / /! Insert props key/ref/__self/__source in this. Props object
    for (propName in config) {
      if( hasOwnProperty.call(config, propName) && ! RESERVED_PROPS.hasOwnProperty(propName) ) { props[propName] = config[propName]; }}}// Children can be more than one argument, and those are transferred onto
  // the newly allocated props object.
  / /! We can pass more than one argument to props except for the first two (type) and config (children)
  const childrenLength = arguments.length - 2;
  if (childrenLength === 1) {
    props.children = children;
  } else if (childrenLength > 1) {
    const childArray = Array(childrenLength);
    for (let i = 0; i < childrenLength; i++) {
      childArray[i] = arguments[i + 2];
    }
    if (__DEV__) {
      if (Object.freeze) {
        Object.freeze(childArray);
      }
    }
    props.children = childArray;
  }

  / /! See if the class component has a default props object as well
  //class Cmp extends React.Component cmp. defaulrProps = {key:value} Is equivalent to setting static properties for a class
  if (type && type.defaultProps) {
    const defaultProps = type.defaultProps;
    for (propName in defaultProps) {
      if (props[propName] === undefined) { props[propName] = defaultProps[propName]; }}}/ /! Dev regardless of
  if (__DEV__) {
    if (key || ref) {
      const displayName =
        typeof type === 'function'
          ? type.displayName || type.name || 'Unknown'
          : type;
      if (key) {
        defineKeyPropWarningGetter(props, displayName);
      }
      if(ref) { defineRefPropWarningGetter(props, displayName); }}}/ /! Return a React element
  return ReactElement(
    type,
    key,
    ref,
    self,
    source,
    ReactCurrentOwner.current,
    props,
  );
}
Copy the code

3.ReactBaseClasses.js

Component/pureComponent implementation

//React/ReactBaseClasses.js
function Component(props, context, updater) {
  this.props = props;
  this.context = context;
  // If a component has string refs, we will assign a different object later.
  this.refs = emptyObject; // The string ref is retrieved here
  // We initialize the default updater but the real one gets injected by the
  // renderer.
  this.updater = updater || ReactNoopUpdateQueue;
}

Component.prototype.isReactComponent = {};



/ /! PartialState is either an object or a function
Component.prototype.setState = function(partialState, callback) {
  invariant(
    typeof partialState === 'object' ||
      typeof partialState === 'function' ||
      partialState == null.'setState(...) : takes an object of state variables to update or a ' +
      'function which returns an object of state variables.',);/ /! Call the enqueueSetState function of the updater passed in at initialization to update the data view. This part of the function is in the React-DOM. That's why we passed in this update object
  this.updater.enqueueSetState(this, partialState, callback, 'setState');
};

/**
 * Forces an update. This should only be invoked when it is known with
 * certainty that we are **not** in a DOM transaction.
 *
 * You may want to call this when you know that some deeper aspect of the
 * component's state has changed but `setState` was not called.
 *
 * This will not invoke `shouldComponentUpdate`, but it will invoke
 * `componentWillUpdate` and `componentDidUpdate`.
 *
 * @param {? function} callback Called after update is complete.
 * @final
 * @protected* /
/ /! The prototype method calls the pdater object. The enqueueForceUpdate method forces the component to refresh
Component.prototype.forceUpdate = function(callback) {
  this.updater.enqueueForceUpdate(this, callback, 'forceUpdate');
};

Copy the code
//React/ReactBaseClasses.js function ComponentDummy() {} ComponentDummy.prototype = Component.prototype; /** * Convenience component with default shallow equality check for sCU. */ function PureComponent(props, context, updater) { this.props = props; this.context = context; // If a component has string refs, we will assign a different object later. this.refs = emptyObject; this.updater = updater || ReactNoopUpdateQueue; } const pureComponentPrototype = (PureComponent.prototype = new ComponentDummy()); / /! Only realize now inherit pureComponentPrototype. Constructor = PureComponent; // Avoid an extra prototype jump for these methods. Object.assign(pureComponentPrototype, Component.prototype); pureComponentPrototype.isPureReactComponent = true; / /! Export {Component, PureComponent}; export {Component, PureComponent};Copy the code

4. Ref

Ref is used to get node instances. There are three ways to use ref. Only class components and native DOM tags can have ref, because ref gets instance instances. Functions don’t have instance instances (because there is no this). Dom is the dom element), the function component does not have a ref. To use these three methods you must use the forwardRef to get the ref.

Three kinds of ref: string ref/ function re/f object ref

//ref three ways
import React, {Component} from "react";

class Myref extends React.Component {
  constructor(props) {
    super(props);
    this.state = {};
    this.objRef= React.createRef() / /! The only way to get an instance from a ref is through the.current form
    this.FunRef = null
  }
  componentDidMount(){
    setTimeout(() = >{
      this.objRef.current.innerHTML = 'bang'
      this.refs.stringRef.innerHTML = 'bang'
      this.FunRef.innerHTML = 'bang'
    },3000)}render() {
    return (
      <>
      <div ref={this.objRef}>objref</div>
      <div ref="stringRef">stringRef</div>
      <div ref={ele= >{this.FunRef=ele}}>funRef</div>
      </>); }}export default Myref;
Copy the code

So here we have the createRef form createRef which is an object but in the current property

//react/ReactCreateRef 
export function createRef() :RefObject {
  const refObject = {
    current: null};if (__DEV__) {
    Object.seal(refObject);
  }
  return refObject;
}
Copy the code

5. ForwardRef explanation

React.forwardRef resolves the issue of the function component not being able to use the ref to pass to the dom element inside the function component that actually gets the instance

/ / the demo cases
import React, {Component} from "react";

class MyforwardRef extends React.Component {
  constructor(props) {
    super(props);
    this.state = {};
    this.ref = React.createRef()
  }
  componentDidMount(){
    setTimeout(() = >{
      this.ref.current.value = 'bang'
    },3000)}render() {
    return (
      <Child ref={this.ref}></Child>); }}/ /! Ref does not belong to props
let Child=  React.forwardRef((props,ref) = >{
  / /! Ref passes to the desired DOM
  return <input  ref = {ref}></input>
})
export default MyforwardRef;
Copy the code
//React/forwardRef
/ /! Render is the function component that is passed in
export default function forwardRef<Props.ElementType: React$ElementType> (
  render: (props: Props, ref: React$Ref<ElementType>) => React$Node,
) {
  if (__DEV__) {
    if (typeofrender ! = ='function') {
      warningWithoutStack(
        false.'forwardRef requires a render function but was given %s.',
        render === null ? 'null' : typeof render,
      );
    } else {
      warningWithoutStack(
        // Do not warn for 0 arguments because it could be due to usage of the 'arguments' object
        render.length === 0 || render.length === 2.'forwardRef render functions accept exactly two parameters: props and ref. %s',
        render.length === 1
          ? 'Did you forget to use the ref parameter? '
          : 'Any additional parameter will be undefined.',); }if(render ! =null) {
      warningWithoutStack(
        render.defaultProps == null && render.propTypes == null.'forwardRef render functions do not support propTypes or defaultProps. ' +
          'Did you accidentally pass a React component? ',); }}// Return an object
  return {
    $$typeof: REACT_FORWARD_REF_TYPE, / /! Give a specific ref_type
    render,/ /! Render is the function component that is passed in
  };
}
Copy the code

Notice one thing

let Child= React.forwardRef((props,ref)=>{ //! Return <input ref = {ref}></input>}) /* Child :{$typeof: REACT_FORWARD_REF_TYPE, //! Give a specific ref_type render,//! Render is the function component passed in}; So */ <Child ref={this.ref}></Child>// createElement const Element ={// This tag allows us to totally identify this as a React Element $$typeof: REACT_ELEMENT_TYPE, //! CreateProtol $$typeof React _protolType_ // built-in properties that belong on the Element type: type, {$$typeof: REACT_FORWARD_REF_TYPE, _typerender}; } // The $$typeof the entire element is still REACT_ELEMENT_TYPECopy the code

6. The context

React.createContext()

/ / use
let userContext = React.createContext()
let userProvider = userContext.Provider
let userConsumer = userContext.Consumer
Copy the code
//React/ReactContextjs
/ /! DefaultValue the default value
/ /! CalculateChangedBits calculates changes to the old and new context and then to the new context
export function createContext<T> (defaultValue: T, calculateChangedBits: ? (a: T, b: T) => number,) :ReactContext<T> {
  if (calculateChangedBits === undefined) {
    calculateChangedBits = null;
  } else {
    if (__DEV__) {
      warningWithoutStack(
        calculateChangedBits === null ||
          typeof calculateChangedBits === 'function'.'createContext: Expected the optional second argument to be a ' +
          'function. Instead received: %s', calculateChangedBits, ); }}/ /! Create a context object of type context_type and again, just like ref, REACT_CONTEXT_TYPE is stored as the type property of createElement The $$Typeof createElement is always Element
  const context: ReactContext<T> = {
    $$typeof: REACT_CONTEXT_TYPE,
    _calculateChangedBits: calculateChangedBits, / /! CurrentValue is used when we update it later
    // As a workaround to support multiple concurrent renderers, we categorize
    // some renderers as primary and others as secondary. We only expect
    // there to be two concurrent renderers at most: React Native (primary) and
    // Fabric (secondary); React DOM (primary) and React ART (secondary).
    // Secondary renderers store their context values on separate fields.
    _currentValue: defaultValue,/ /! Record the latest context value. These two are just different platforms
    _currentValue2: defaultValue,
    // These are circular
    Provider: (null: any),
    Consumer: (null: any),
  };
  / /! The provider object
  context.Provider = {
    $$typeof: REACT_PROVIDER_TYPE,
    _context: context,
  };

  let hasWarnedAboutUsingNestedContextConsumers = false;
  let hasWarnedAboutUsingConsumerProvider = false;

  if (__DEV__) {
    // A separate object, but proxies back to the original context object for
    // backwards compatibility. It has a different $$typeof, so we can properly
    // warn for the incorrect usage of Context as a Consumer.
    / /! The Consumer object has the context property so you can get the latest _currentValue in the context object
    const Consumer = {
      $$typeof: REACT_CONTEXT_TYPE,
      _context: context,
      _calculateChangedBits: context._calculateChangedBits,/ /! CurrentValue is used when we update it later
    };
    // $FlowFixMe: Flow complains about not setting a value, which is intentional here
    / /! Get the latest Provider CONSUMber _currentValue
    Object.defineProperties(Consumer, {
      Provider: {
        get() {
          if(! hasWarnedAboutUsingConsumerProvider) { hasWarnedAboutUsingConsumerProvider =true;
            warning(
              false.'Rendering <Context.Consumer.Provider> is not supported and will be removed in ' +
                'a future major release. Did you mean to render 
      
        instead? '
      ,); }return context.Provider;
        },
        set(_Provider){ context.Provider = _Provider; }},_currentValue: {
        get() {
          return context._currentValue;
        },
        set(_currentValue){ context._currentValue = _currentValue; }},_currentValue2: {
        get() {
          return context._currentValue2;
        },
        set(_currentValue2){ context._currentValue2 = _currentValue2; }},Consumer: {
        get() {
          if(! hasWarnedAboutUsingNestedContextConsumers) { hasWarnedAboutUsingNestedContextConsumers =true;
            warning(
              false.'Rendering <Context.Consumer.Consumer> is not supported and will be removed in ' +
                'a future major release. Did you mean to render 
      
        instead? '
      ,); }returncontext.Consumer; ,}}});// $FlowFixMe: Flow complains about missing properties because it doesn't understand defineProperty
    context.Consumer = Consumer;
  } else {
    context.Consumer = context;
  }

  if (__DEV__) {
    context._currentRenderer = null;
    context._currentRenderer2 = null;
  }

  return context;
}

Copy the code

7. ConcurrentMode Task scheduling

Task process can be prioritized to distinguish the execution of high priority and can be interrupted to achieve task scheduling, JS single thread, if there is no task scheduling, then the execution of animation will lag after the update

/ / use cases
import React, { ConcurrentMode } from 'react'
import { flushSync } from 'react-dom'/ /! FlushSync: Flushes incoming function tasks to the highest priority

import './index.css'

class Parent extends React.Component {
  state = {
    async: true.num: 1.length: 2000,}componentDidMount() {
    this.interval = setInterval(() = > {
      this.updateNum()
    }, 200)}componentWillUnmount() {
    // Don't forget to clear interval
    if (this.interval) {
      clearInterval(this.interval)
    }
  }

  updateNum() {
    const newNum = this.state.num === 3 ? 0 : this.state.num + 1
    / /! Animation and updateNum have the same priority so that the numbers don't change as fast in sync
    if (this.state.async) {
      this.setState({
        num: newNum,
      })
    } else {
      / /! Make setState a high priority task so that the number changes don't get stuck but the animation might
      flushSync(() = > {
        this.setState({
          num: newNum,
        })
      })
    }
  }

  render() {
    const children = []

    const { length, num, async } = this.state

    for (let i = 0; i < length; i++) {
      children.push(
        <div className="item" key={i}>
          {num}
        </div>)},return (
      <div className="main">
        async:{' '}
        <input
          type="checkbox"
          checked={async}
          onChange={()= >flushSync(() => this.setState({ async: ! async }))} /><div className="wrapper">{children}</div>
      </div>)}export default() = > (<ConcurrentMode>
    <Parent />
  </ConcurrentMode>)}Copy the code
//React/React.js if (enableStableConcurrentModeAPIs) { React.ConcurrentMode = REACT_CONCURRENT_MODE_TYPE; / /! The ConcurrentMode component is the =REACT_CONCURRENT_MODE_TYPE, which is a sysmbol flag: React.Profiler = REACT_PROFILER_TYPE; } else { React.unstable_ConcurrentMode = REACT_CONCURRENT_MODE_TYPE; React.unstable_Profiler = REACT_PROFILER_TYPE; }Copy the code

8.suspense

Componentsto throw a promise in Suspense and show fallback content if the promise is not resolved. Componentsto refresh the component after resolve, rendering the true internal component content

Use: this is usually used within a component to load data asynchronously, usually in conjunction with lazy, which throws a promise before the component is finished loading and reslove the promise after loading

//LazyComp is a component that is loaded asynchronously. The fallback content is displayed only after the asynchronous component is loaded
import React, { Suspense, lazy } from 'react'

const LazyComp = lazy(() = > import('./lazy.js'))

let data = ' '
let promise = ' '
function requestData() {
  if (data) return data
  if (promise) throw promise
  promise = new Promise(resolve= > {
    setTimeout(() = > {
      data = 'Data resolved'
      resolve()
    }, 2000)})throw promise
}

function SuspenseComp() {
  const data = requestData()

  return <p>{data}</p>
}

export default() = > (<Suspense fallback="loading data">
    <SuspenseComp />
    <LazyComp />
  </Suspense>
)
Copy the code
  Suspense: REACT_SUSPENSE_TYPE, // It's a SYsmbol
 //React/ReactLazy.js
      import {REACT_LAZY_TYPE} from 'shared/ReactSymbols';
/ /! Take a function that returns a Thenable
      
        object which is.then is a function which is usually a promise
      ,>
/ /! Return a LazyComponent object whose $$Typeof is REACT_LAZY_TYPE, like ref and context, is the typeof createElementd instead of $$typr because JSX calls createElement The tag is passed in as type
/ /! _status Records the state of this Thenable (usually the state of a Promise)
export function lazy<T.R> (ctor: () => Thenable<T, R>) :LazyComponent<T> {
  return {
    $$typeof: REACT_LAZY_TYPE,
    _ctor: ctor,
    // React uses these fields to store the result.
    _status: -1./ /! _status Records the state of this Thenable (usually the state of a Promise)
    _result: null./ /! _result records the resolve result of this promise, which is the lazy-loaded component}; } so this _status-1$$typeof=== REACT_LAZY_TYPE (); return result (" fallback ")Copy the code

9.hooks

// In the packaged file
if (enableHooks) {
  React.useCallback = useCallback;
  React.useContext = useContext;
  React.useEffect = useEffect;
  React.useImperativeMethods = useImperativeMethods;
  React.useLayoutEffect = useLayoutEffect;
  React.useMemo = useMemo;
  React.useMutationEffect = useMutationEffect;
  React.useReducer = useReducer;
  React.useRef = useRef;
  React.useState = useState;
}
var ReactCurrentOwner = {
  / * * *@internal
   * @type {ReactComponent}* /
  current: null./ /! The current node instance
  currentDispatcher: null / /! The currentDispatcher object that corresponds to the instance is platform-specific and then it's passed in in the React-DOM with the useState method and so on
};
function resolveDispatcher() {
  var dispatcher = ReactCurrentOwner.currentDispatcher;/ /! ReactCurrentOwner is a global class and you have to pass an instance of it in the React-DOM! (dispatcher ! = =null)? invariant(false.'Hooks can only be called inside the body of a function component.') : void 0;
  return dispatcher;
}

function useContext(Context, observedBits) {
  var dispatcher = resolveDispatcher();
  {
    // TODO: add a more generic warning for invalid values.
    if(Context._context ! = =undefined) {
      var realContext = Context._context;
      // Don't deduplicate because this legitimately causes bugs
      // and nobody should be using this in existing code.
      if (realContext.Consumer === Context) {
        warning$1(false.'Calling useContext(Context.Consumer) is not supported, may cause bugs, and will be ' + 'removed in a future major release. Did you mean to call useContext(Context) instead? ');
      } else if (realContext.Provider === Context) {
        warning$1(false.'Calling useContext(Context.Provider) is not supported. ' + 'Did you mean to call useContext(Context) instead? '); }}}return dispatcher.useContext(Context, observedBits);
}

function useState(initialState) {
  var dispatcher = resolveDispatcher();
  return dispatcher.useState(initialState);
}

function useReducer(reducer, initialState, initialAction) {
  var dispatcher = resolveDispatcher();
  return dispatcher.useReducer(reducer, initialState, initialAction);
}

function useRef(initialValue) {
  var dispatcher = resolveDispatcher();
  return dispatcher.useRef(initialValue);
}

function useEffect(create, inputs) {
  var dispatcher = resolveDispatcher();
  return dispatcher.useEffect(create, inputs);
}

function useMutationEffect(create, inputs) {
  var dispatcher = resolveDispatcher();
  return dispatcher.useMutationEffect(create, inputs);
}

function useLayoutEffect(create, inputs) {
  var dispatcher = resolveDispatcher();
  return dispatcher.useLayoutEffect(create, inputs);
}

function useCallback(callback, inputs) {
  var dispatcher = resolveDispatcher();
  return dispatcher.useCallback(callback, inputs);
}

function useMemo(create, inputs) {
  var dispatcher = resolveDispatcher();
  return dispatcher.useMemo(create, inputs);
}

function useImperativeMethods(ref, create, inputs) {
  var dispatcher = resolveDispatcher();
  return dispatcher.useImperativeMethods(ref, create, inputs);
}

Copy the code

10.Children

The React. Children operation child element is an object with methods like map

 Children: {
    map,
    forEach,
    count,
    toArray,
    only,
  },
Copy the code

The react.children. Map must return a one-dimensional array (c1,c1,c1,c2,c2,c2) that is not nested

console.log(React.Children.map(props.children, c= > [c, [c, c]]))
Array(6)
0: {$$typeof: Symbol(react.element), type: "span".key: ". 0 /. 0".ref: null.props: {... },... }1: {$$typeof: Symbol(react.element), type: "span".key: ". / 0. 1-0".ref: null.props: {... },... }2: {$$typeof: Symbol(react.element), type: "span".key: 1:1 ". 0 /.".ref: null.props: {... },... }3: {$$typeof: Symbol(react.element), type: "span".key: ". 1 /. 0".ref: null.props: {... },... }4: {$$typeof: Symbol(react.element), type: "span".key: ". 1 /. 1-0. "".ref: null.props: {... },... }5: {$$typeof: Symbol(react.element), type: "span".key: 1:1 ". 1 /.".ref: null.props: {... },... }length: 6
__proto__: Array(0)
Copy the code

React.children.map is the process that calls mapChildren

process

function mapChildren(children, func, context) {
  if (children == null) {
    return children;
  }
  const result = [];
  / /! The children result array func is the callback that we passed in the context regardless
  mapIntoWithKeyPrefixInternal(children, result, null, func, context);
  return result;
}
  / /! The children result array func is the callback that we passed in the context regardless
function mapIntoWithKeyPrefixInternal(children, array, prefix, func, context) {
  let escapedPrefix = ' ';
  if(prefix ! =null) {
    escapedPrefix = escapeUserProvidedKey(prefix) + '/';
  }
  / /! Get the TraverseContext object
  const traverseContext = getPooledTraverseContext(
    array,
    escapedPrefix,/ /! That's the key that handles the element
    func,/ /! The callback function
    context,
  );
  / /! Children sub-elements mapSingleChildIntoContext built-in function traverseContext context in the pool
  traverseAllChildren(children, mapSingleChildIntoContext, traverseContext);
  releaseTraverseContext(traverseContext);
}
const POOL_SIZE = 10;
const traverseContextPool = [];
function getPooledTraverseContext(mapResult, keyPrefix, mapFunction, mapContext,) {
  / /! TraverseContextPool global variable if there is only this property this property but Null reduces the overhead of creating and deleting the property
  if (traverseContextPool.length) {
    const traverseContext = traverseContextPool.pop();
    traverseContext.result = mapResult;
    traverseContext.keyPrefix = keyPrefix;
    traverseContext.func = mapFunction;
    traverseContext.context = mapContext;
    traverseContext.count = 0;
    return traverseContext;
  } else {
    return {
      result: mapResult,
      keyPrefix: keyPrefix,
      func: mapFunction,
      context: mapContext,
      count: 0}; }}function traverseAllChildren(children, callback, traverseContext) {
  if (children == null) {
    return 0;
  }

  return traverseAllChildrenImpl(children, ' ', callback, traverseContext);
}
/ /! BookKeeping is the context object in the Pool and the child is the key of the child element of the individual node childKey
function mapSingleChildIntoContext(bookKeeping, child, childKey) {
  const {result, keyPrefix, func, context} = bookKeeping;

  let mappedChild = func.call(context, child, bookKeeping.count++);/ /! Func is the callback function passed in
  if (Array.isArray(mappedChild)) { / /! Check whether the callback function is an array c=>[c,c]
    / /! We're going to add the context to the pool so we can use that to reduce memory
    mapIntoWithKeyPrefixInternal(mappedChild, result, childKey, c= > c);/ /! We continue to recursively call the array but instead of calling the previous callback c=>[c,c],c =>c returns itself
  } else if(mappedChild ! =null) {
    if (isValidElement(mappedChild)) {/ /! A single element determines whether a react-element is valid
      mappedChild = cloneAndReplaceKey(/ /! If you modify the key, other attributes remain unchanged
        mappedChild,
        // Keep both the (mapped) and old keys if they differ, just as
        // traverseAllChildren used to do for objects as childrenkeyPrefix + (mappedChild.key && (! child || child.key ! == mappedChild.key) ? escapeUserProvidedKey(mappedChild.key) +'/'
            : ' ') +
          childKey,
      );
    }
    result.push(mappedChild);/ /! Finally, the single element enters the result array}}function traverseAllChildrenImpl(children, nameSoFar, callback, traverseContext,) {
 
  const type = typeof children;

  if (type === 'undefined' || type === 'boolean') {
    // All of the above are perceived as null.
    children = null;
  }

  let invokeCallback = false;

  if (children === null) {
    invokeCallback = true;
  } else {
    switch (type) {
      case 'string':
      case 'number':
        invokeCallback = true;
        break;
      case 'object':
        switch (children.$$typeof) {
          case REACT_ELEMENT_TYPE:
          case REACT_PORTAL_TYPE:
            invokeCallback = true; }}}/ /! Children is a single node that calls callback directly, which is called maoSingleChildToContxt
  if (invokeCallback) {
    callback(
      traverseContext,
      children,
      // If it's the only child, treat the name as if it was wrapped in an array
      // so that it's consistent if the number of children grows.
      nameSoFar === ' ' ? SEPARATOR + getComponentKey(children, 0) : nameSoFar,
    );
    return 1;
  }

  let child;
  let nextName;
  let subtreeCount = 0; // Count of children found in the current subtree.
  const nextNamePrefix =
    nameSoFar === ' ' ? SEPARATOR : nameSoFar + SUBSEPARATOR;
  / /! The children is an array
  if (Array.isArray(children)) {
    for (let i = 0; i < children.length; i++) {
      child = children[i];
      nextName = nextNamePrefix + getComponentKey(child, i);
      / /! Iterate over each child node recursively
      subtreeCount += traverseAllChildrenImpl(
        child,
        nextName,/ /! Child element key value processingcallback, traverseContext, ); }}else {
    const iteratorFn = getIteratorFn(children);
    if (typeof iteratorFn === 'function') {
      if (__DEV__) {
        // Warn about using Maps as children
        if (iteratorFn === children.entries) {
          warning(
            didWarnAboutMaps,
            'Using Maps as children is unsupported and will likely yield ' +
              'unexpected results. Convert it to a sequence/iterable of keyed ' +
              'ReactElements instead.',); didWarnAboutMaps =true; }}const iterator = iteratorFn.call(children);
      let step;
      let ii = 0;
      while (!(step = iterator.next()).done) {
        child = step.value;
        nextName = nextNamePrefix + getComponentKey(child, ii++);
        subtreeCount += traverseAllChildrenImpl(
          child,
          nextName,
          callback,
          traverseContext,
        );
      }
    } else if (type === 'object') {
      let addendum = ' ';
      if (__DEV__) {
        addendum =
          ' If you meant to render a collection of children, use an array ' +
          'instead.' +
          ReactDebugCurrentFrame.getStackAddendum();
      }
      const childrenString = ' ' + children;
      invariant(
        false.'Objects are not valid as a React child (found: %s).%s',
        childrenString === '[object Object]'
          ? 'object with keys {' + Object.keys(children).join(', ') + '} ': childrenString, addendum, ); }}return subtreeCount;
}
Copy the code

11. Other apis

The memo is passed in as a component and the new and old props method returns an object. $$type is REACT_MEMO_TYPE, which means the component will be treated as a pureComponent

export default function memo<Props>( type: React$ElementType, compare? : (oldProps: Props, newProps: Props) => boolean, ) { if (__DEV__) { if (! isValidElementType(type)) { warningWithoutStack( false, 'memo: The first argument must be a component. Instead ' + 'received: %s', type === null ? 'null' : typeof type, ); } } return { $$typeof: REACT_MEMO_TYPE, type, compare: compare === undefined ? null : compare, };Copy the code

2.Fragment: REACT_FRAGMENT_TYPE,

3.StrictMode: REACT_STRICT_MODE_TYPE, the following nodes adopt a StrictMode, expired functions will be reminded

4.cloneElement

export function cloneElement(element, config, children) {
  / /! It's similar to createElement except that we pass in an Element and we clone it, and then config has the new properties added to childre and ps to the props of the original Element, and children will be overriddeninvariant( ! (element ===null || element === undefined),
    'React.cloneElement(...) : The argument must be a React element, but you passed %s.',
    element,
  );

  let propName;

  // Original props are copied
  const props = Object.assign({}, element.props);

  // Reserved names are extracted
  let key = element.key;
  let ref = element.ref;
  // Self is preserved since the owner is preserved.
  const self = element._self;
  // Source is preserved since cloneElement is unlikely to be targeted by a
  // transpiler, and the original source is probably a better indicator of the
  // true owner.
  const source = element._source;

  // Owner will be preserved, unless ref is overridden
  let owner = element._owner;

  if(config ! =null) {
    if (hasValidRef(config)) {
      // Silently steal the ref from the parent.
      ref = config.ref;
      owner = ReactCurrentOwner.current;
    }
    if (hasValidKey(config)) {
      key = ' ' + config.key;
    }

    // Remaining properties override existing props
    let defaultProps;
    if (element.type && element.type.defaultProps) {
      defaultProps = element.type.defaultProps;
    }
    for (propName in config) {
      if( hasOwnProperty.call(config, propName) && ! RESERVED_PROPS.hasOwnProperty(propName) ) {if (config[propName] === undefined&& defaultProps ! = =undefined) {
          // Resolve default props
          props[propName] = defaultProps[propName];
        } else{ props[propName] = config[propName]; }}}}// Children can be more than one argument, and those are transferred onto
  // the newly allocated props object.
  const childrenLength = arguments.length - 2;
  if (childrenLength === 1) {
    props.children = children;
  } else if (childrenLength > 1) {
    const childArray = Array(childrenLength);
    for (let i = 0; i < childrenLength; i++) {
      childArray[i] = arguments[i + 2];
    }
    props.children = childArray;
  }

  return ReactElement(element.type, key, ref, self, source, owner, props);
}
Copy the code

Createfactory Type = createFactory type; createFactory type = createFactory Type

export function createFactory(type) {
  const factory = createElement.bind(null, type);
  // Expose the type on the factory and the prototype so that it can be
  // easily accessed on elements. E.g. `<Foo />.type === Foo`.
  // This should not be named `constructor` since this may not be the function
  // that created the element, and it may not even be a constructor.
  // Legacy hook: remove it
  factory.type = type;
  return factory;
}
Copy the code

conclusion

$$typeof = $$typeof; $$typeof = $$typeof; $$typeof = $$typeof; $$typeof = $$typeof