React源码解析1-React包

368 阅读3分钟

React这个包目录

image-20210420150534502

1.React.js是入口 外部能使用的api全在这里导出

/**
 * 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,
	//原生组件
  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;

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, //!标识是React内部element元素 对比React.createProtol 这个 $$typeof 是React的_protoltype_

    // Built-in properties that belong on the element
    type: type, //!传进来的元素类型
    key: key,
    ref: ref,
    props: props,

    // Record the component responsible for creating this element.
    _owner: owner,
  };
  return element
 }
//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;
  //!看看有没有合理的ref和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
    //! 再看是不是内嵌的props key/ref/__self/__source 这些都不该出现在this.props里面 放到props这个新对象里面
    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.
  //!处理children 因为传入的参数可以多个除了前两个是type,config 后面都是children 剩下的参数转成children数组放到props上
  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;
  }

  //!看看类组件有没有默认的props 也放到props对象来
  //class Cmp extends React.Component     Cmp.defaulrProps = {key:value} 相当于给类设置静态属性 有则不设置 没有则设置
  if (type && type.defaultProps) {
    const defaultProps = type.defaultProps;
    for (propName in defaultProps) {
      if (props[propName] === undefined) {
        props[propName] = defaultProps[propName];
      }
    }
  }
  //!Dev不管
  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);
      }
    }
  }
  //!返回一个React元素
  return ReactElement(
    type,
    key,
    ref,
    self,
    source,
    ReactCurrentOwner.current,
    props,
  );
}

3.ReactBaseClasses.js

component/pureComponent实现

//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; //string形式的ref在这里获取
  // We initialize the default updater but the real one gets injected by the
  // renderer.
  this.updater = updater || ReactNoopUpdateQueue;
}

Component.prototype.isReactComponent = {};



//!类上面的setState原型方法 partialState是对象或者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.',
  );
  //!调用初始化时候传入的updater的enqueueSetState函数去更新数据视图 这部分函数是在react-dom里(和平台有关 因为要更新视图) 这就是为什么要传入这门一个更新对象进来 为了区分不同平台的更新函数
  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
 */
//!原型方法 去调用pdater对象.enqueueForceUpdate方法去强制刷新组件
Component.prototype.forceUpdate = function(callback) {
  this.updater.enqueueForceUpdate(this, callback, 'forceUpdate');
};

//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()); //!实现啦继承而已
pureComponentPrototype.constructor = PureComponent;
// Avoid an extra prototype jump for these methods.
Object.assign(pureComponentPrototype, Component.prototype);
pureComponentPrototype.isPureReactComponent = true;//!就加了一个属性标识 继承这个pure类都有这个属性 后续更新时候判断属性是否变化再去更新

export {Component, PureComponent};

4.ref讲解

ref 用来获取节点具体实例,有三种方法使用ref 只有类组件和原生dom标签才能有ref,因为ref拿到的是具体实例,而函数是没有具体实例的(因为没有this),类/原生dom是有实例(比如类是new Cmp()这个实例,dom就是这个dom元素),函数组件没有ref,要想使用这三个方法必须用forwardRef拿到ref。

三种ref:string ref/函数re/f对象ref

//ref三种方式
import React, {Component} from "react";

class Myref extends React.Component {
  constructor(props) {
    super(props);
    this.state = {};
    this.objRef= React.createRef() //!只有这个方式的ref是要通过.current形式获取实例的 其他方式都是直接是实例
    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;

这里是createRef形式创建ref 里面就是个对象 不过存在current属性里

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

5.forwardRef讲解

React.forwardRef 为了解决函数组件无法用ref的困局 ref传到函数组件内部的真正要获取实例的dom元素上去

//demo用例
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不属于props
let Child=  React.forwardRef((props,ref)=>{
  //!ref传到想要的dom上去
  return <input  ref = {ref}></input>
})
export default MyforwardRef;
//React/forwardRef
//! render就是传进来的函数组件 
export default function forwardRef<Props, ElementType: React$ElementType>(
  render: (props: Props, ref: React$Ref<ElementType>) => React$Node,
) {
  if (__DEV__) {
    if (typeof render !== '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 {
    $$typeof: REACT_FORWARD_REF_TYPE, //!给一个特定的ref_type
    render,//! render就是传进来的函数组件
  };
}

注意一个东西

let Child=  React.forwardRef((props,ref)=>{
  //!ref传到想要的dom上去
  return <input  ref = {ref}></input>
})
/*此时child是这个对象:{
    $$typeof: REACT_FORWARD_REF_TYPE, //!给一个特定的ref_type
    render,//! render就是传进来的函数组件
  };
  然后*/
   <Child ref={this.ref}></Child>//这个代码会执行createElement
   const element = {
    // This tag allows us to uniquely identify this as a React Element
    $$typeof: REACT_ELEMENT_TYPE, //!标识是React内部element元素 对比React.createProtol 这个 $$typeof 是React的_protoltype_

    // Built-in properties that belong on the element
    type: type, //这个type就是{$$typeof: REACT_FORWARD_REF_TYPE, _typerender}对象
  };
    }
    //而整体元素的$$typeof还是REACT_ELEMENT_TYPE

6.context讲解

React.createContext()

//使用
let userContext = React.createContext()
let userProvider = userContext.Provider
let userConsumer = userContext.Consumer
//React/ReactContextjs
//!defaultValue默认值
//!calculateChangedBits 计算新老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,
      );
    }
  }
  //!创建一个context对象 type为context_type 这里也是和ref一样 REACT_CONTEXT_TYPE,也是作为createElement元素的的type属性存储的 createElement元素的$$typeof一直是element
  const context: ReactContext<T> = {
    $$typeof: REACT_CONTEXT_TYPE,
    _calculateChangedBits: calculateChangedBits, //!后面更新时候currentValue用
    // 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,//!记录最新的context值 这两个只是平台不一样
    _currentValue2: defaultValue,
    // These are circular
    Provider: (null: any),
    Consumer: (null: any),
  };
  //!provider对象
  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.
    //!Consumer对象 有context属性 所以可以拿到context对象里的最新的_currentValue
    const Consumer = {
      $$typeof: REACT_CONTEXT_TYPE,
      _context: context,
      _calculateChangedBits: context._calculateChangedBits,//!后面更新时候currentValue用
    };
    // $FlowFixMe: Flow complains about not setting a value, which is intentional here
    //!拿到最新的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 <Context.Provider> 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 <Context.Consumer> instead?',
            );
          }
          return context.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;
}

7.concurrentMode 任务调度

任务过程可以优先级区分 优先级高的执行而且可以中断,实现任务调度,js单线程,如果没有任务调度,那么在更新时候后在执行动画会卡顿

//用例
import React, { ConcurrentMode } from 'react'
import { flushSync } from 'react-dom'//!flushSync:把传入的函数任务提高到最高的优先级

import './index.css'

class Parent extends React.Component {
  state = {
    async: true,
    num: 1,
    length: 2000,
  }

  componentDidMount() {
    this.interval = setInterval(() => {
      this.updateNum()
    }, 200)
  }

  componentWillUnmount() {
    // 别忘了清除interval
    if (this.interval) {
      clearInterval(this.interval)
    }
  }

  updateNum() {
    const newNum = this.state.num === 3 ? 0 : this.state.num + 1
    //!动画和updateNum一个优先级 这样就同步进行 数字变化没那么快
    if (this.state.async) {
      this.setState({
        num: newNum,
      })
    } else {
      //!让setState变成优先级高的任务 这样数字变化就不会卡顿 但是动画可能会卡
      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>
)
}
//React/React.js
if (enableStableConcurrentModeAPIs) {
  React.ConcurrentMode = REACT_CONCURRENT_MODE_TYPE;//!ConcurrentMode这个组件就是=REACT_CONCURRENT_MODE_TYPE就是个sysmbol一个标志:<ConcurrentMode><Parent /></ConcurrentMode>那他是如何承载children的呢
  React.Profiler = REACT_PROFILER_TYPE;
} else {
  React.unstable_ConcurrentMode = REACT_CONCURRENT_MODE_TYPE;
  React.unstable_Profiler = REACT_PROFILER_TYPE;
}

8.suspense

原理:Suspense 内部组件会throw一个promise 当promise没有resolve前会显示fallback的内容 当内部的promise的状态resolve后会重新刷新组件,渲染真正的内部组件内容

使用:这里一般就可以用于组件内部异步加载数据 通常和lazy一起用 lazy函数在组件没加载完之前抛出一个promise 加载完之后reslove这个promise

//LazyComp是异步加载的一个组件 当该异步组件加载完成后才会显示组件内容 没加载完成前显示fallback内容
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>
)
  Suspense: REACT_SUSPENSE_TYPE, //还是个sysmbol
 //React/ReactLazy.js
      import {REACT_LAZY_TYPE} from 'shared/ReactSymbols';
//!接受一个函数 这个函数返回Thenable<T, R>对象即.then是个函数 一般就是promise
//!返回一个LazyComponent对象 这个对象的 $$typeof是REACT_LAZY_TYPE和ref和context一样是createElementd的type 而不是$$typr 因为jsx都会调用createElement函数 而标签就是当作type传进去
//!_status 记录这个Thenable的状态(一般就是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 记录这个Thenable的状态(一般就是Promise的状态)
    _result: null,//!_result 记录这个promise的resolve结果 即lazy加载的组件
  };
}
所以这个_status-1的时候就抛出一个promise让他执行fallback 后面加载成功的时候在去返回result 这部分逻辑应该是在createElement的判断
type.$$typeof=== REACT_LAZY_TYPE 时候做处理

9.hooks

//打包后的文件里
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,//!当前的节点实例
  currentDispatcher: null //!实例对应的currentDispatcher对象 和平台有关 后续在react-dom里面传进来 上面有useState等方法
};
function resolveDispatcher() {
  var dispatcher = ReactCurrentOwner.currentDispatcher;//!ReactCurrentOwner是个全局的类 这个设置得在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);
}

10.Children

React.children 操作子元素 是个对象 有map等方法

 Children: {
    map,
    forEach,
    count,
    toArray,
    only,
  },

React.children.map 最后返回的一定是一维数组 即[c1,c1,c1,c2,c2,c2]不会嵌套

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: ".0/.1:1", 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)

React.children.map就是调用mapchildren的流程

流程

image-20210421105834026

function mapChildren(children, func, context) {
  if (children == null) {
    return children;
  }
  const result = [];
  //!children 子元素 result结果数组 func就是我们传入的回调函数 context不管
  mapIntoWithKeyPrefixInternal(children, result, null, func, context);
  return result;
}
  //!children 子元素 result结果数组 func就是我们传入的回调函数 context不管
function mapIntoWithKeyPrefixInternal(children, array, prefix, func, context) {
  let escapedPrefix = '';
  if (prefix != null) {
    escapedPrefix = escapeUserProvidedKey(prefix) + '/';
  }
  //!获取TraverseContext对象
  const traverseContext = getPooledTraverseContext(
    array,
    escapedPrefix,//!就是处理元素的key
    func,//!回调函数  
    context,
  );
  //!children子元素 mapSingleChildIntoContext内置函数 traverseContext  pool里的context
  traverseAllChildren(children, mapSingleChildIntoContext, traverseContext);
  releaseTraverseContext(traverseContext);
}
const POOL_SIZE = 10;
const traverseContextPool = [];
function getPooledTraverseContext(
  mapResult,
  keyPrefix,
  mapFunction,
  mapContext,
) {
  //!traverseContextPool全局变量 这里面如果有只是有这个属性 这个属性但是为Null 减少的只是创建和删除属性的开销
  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 就是Pool中的context对象 child就是子元素单个节点 childKey子元素的key
function mapSingleChildIntoContext(bookKeeping, child, childKey) {
  const {result, keyPrefix, func, context} = bookKeeping;

  let mappedChild = func.call(context, child, bookKeeping.count++);//!func就是传入的回调函数
  if (Array.isArray(mappedChild)) { //!判断回调函数是不是个数组 c=>[c,c]
    //!这里又会向pool里面添加context 所以数组嵌套层数可以采用这个来减少内存
    mapIntoWithKeyPrefixInternal(mappedChild, result, childKey, c => c);//!继续递归调用这个数组但是回调函数不是之前的回调 c=>[c,c] 而是c=>c返回自身的函数
  } else if (mappedChild != null) {
    if (isValidElement(mappedChild)) {//!单个元素 判断是不是合法的react-element
      mappedChild = cloneAndReplaceKey(//!修改下key 其他属性不变
        mappedChild,
        // Keep both the (mapped) and old keys if they differ, just as
        // traverseAllChildren used to do for objects as children
        keyPrefix +
          (mappedChild.key && (!child || child.key !== mappedChild.key)
            ? escapeUserProvidedKey(mappedChild.key) + '/'
            : '') +
          childKey,
      );
    }
    result.push(mappedChild);//!最终单个元素进入结果数组
  }
}
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是单个节点直接调用callback callback就是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;
  //!children是数组
  if (Array.isArray(children)) {
    for (let i = 0; i < children.length; i++) {
      child = children[i];
      nextName = nextNamePrefix + getComponentKey(child, i);
      //!遍历递归每个子节点
      subtreeCount += traverseAllChildrenImpl(
        child,
        nextName,//!子元素key值处理
        callback,
        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;
}

11.其他api

1.memo 传入一个组件和新旧props对比方法 返回一个对象$$type是 REACT_MEMO_TYPE 表示后续把这个组件当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,
  };

2.Fragment: REACT_FRAGMENT_TYPE,

3.StrictMode: REACT_STRICT_MODE_TYPE, 下面节点都采用一种严格模式,过期的函数会提醒

4.cloneElement

export function cloneElement(element, config, children) {
  //!和createelement差不多 只是我们传入啦一个element 我们对他克隆一份 然后config里面有新增的属性加上 有childre也加上 ps 原先得element的props有children将被覆盖
  invariant(
    !(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);
}

4.createfactory type是我们先指定 后面再创建元素时候不需要给type 批量创建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;
}

总结

1.$$typeof这个属性很关键 作为createElement的type 后续会判断这个属性是上面来进行不同的逻辑