16.6 提供的一个feature,在线源码地址:https://github.com/facebook/react/blob/master/packages/react/src/React.jsreact
在一个Suspense组件,它下面渲染了一个或者多个异步的组件,有任何一个组件throw了一个promise以后,在这个promise的resolved以前,都会显示fallback中的内容。git
也就是说,在一个Suspense组件中,有多个组件,它要等它里面全部组件都resolved以后,才会撤销掉fallback中的内容github
demoapi
// suspense/index.js 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/lazy.js import React from 'react' export default () => <p>Lazy Comp</p>
源码数组
// React.js ... Suspense: REACT_SUSPENSE_TYPE // 仍是一个常量 ...
// https://github.com/facebook/react/blob/master/packages/react/src/ReactLazy.js import type {LazyComponent, Thenable} from 'shared/ReactLazyComponent'; import {REACT_LAZY_TYPE} from 'shared/ReactSymbols'; 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, // 用来记录当前thenable这个对象处于的状态。当渲染到lazy component状态的时候,会调用这个ctor,而后返回一个thenable对象,通常来讲是一个promise,处于pending状态,-1 _result: null, // 用来记录Thenable resolved以后返回的属性,在lazy最终resolved出来的组件,放在里面。后续咱们渲染lazy component的时候,直接拿result }; }
先看一个demopromise
import React from 'react' function ChildrenDemo(props) { console.log(props.children) // 若是React.Children.map 返回的是一个数组,它会继续把它们展开成一维数组 [1, 1, 1, 2, 2, 2] console.log(React.Children.map(props.children, c => [c, [c, c]])) return props.children } export default () => ( <ChildrenDemo> <span>1</span> <span>2</span> </ChildrenDemo> )
在线源码地址浏览器
https://github.com/facebook/react/blob/master/packages/react/src/ReactChildren.js(点击进入)dom
图解源码流程异步
mapIntoWithKeyPrefixInternal性能
【它是一个大递归】,在此作了如下几件事情:
1. 处理key 2. 在此作一个很是重要的事情,就是去context pool中去获取一个context 3. traverseAllChildren 4. 后续全部流程完,会把这个context归还
traverseAllChildren
在此作了如下几件事情:
1. children为null的状况return 0 2. traverseAllChildrenImpl
traverseAllChildrenImpl
【它是一个小递归】,根据react element的type作了如下几件事情:
mapSingleChildIntoContext
作了如下几个事情
小结:源码中运用了递归+资源池这样一个概念去编写相应逻辑。在此谈下对象池,当一个方法多是一个常常要被调用的方法。若是该方法展开的比较多,声明和释放的对象多,这是一个很是须要性能的问题,尤为是在浏览器计算的过程当中,可能须要去重复的去new 和delete一块内存空间,避免内存计算形成的性能抖动,从而去节省一部分的开销
16.6 feature 目的是给function component也提供一个相似pure component的功能
源码
... export default function memo<Props>( type: React$ElementType, compare?: (oldProps: Props, newProps: Props) => boolean, ) { ... return { $$typeof: REACT_MEMO_TYPE, type, compare: compare === undefined ? null : compare, }; }
从上面来看,最终返回了一个$$typeof为REACT_MEMO_TYPE的对象,真正的处理逻辑还须要在react-dom中学习
const functionComponent = () => { return <> <span>1</span> </> }
<> 实际上是React.Fragment
源码
Fragment: REACT_FRAGMENT_TYPE // 依然是一个常量,实际处理逻辑须要在react-dom中查看对此类型的处理
提供一些过期api的提醒
源码
StrictMode: REACT_STRICT_MODE_TYPE // 依然是个symbol
在ReactElement.js源码中,实现了对element进行了clone的逻辑