# React16 版本解决了哪些问题,加了哪些东西

# 上期回顾:

# React 项目有哪些优化点

  • 保证数据的不可变性
  • 使用唯一的键值迭代
  • 使用 webWork 做密集型输出
  • 不在 render 中处理数据
  • 不必要的标签,使用 React.Fragments
  • 对于 CSR 或 SSR,都使用 Service worker 来资源调配及骨架图,CSR 用懒加载,SSR 服务端用 stream 流处理
  • 尽可能把 FCP 提前
  • 使用 React.Profiler 分析渲染的一些任务
  • 使用 PureComponent 及 React.memo 等做浅对比,用 ShouldComponentUpdate 做深比较。
  • 尽量减少 render,使用 React.useMemo 与 React.useCallback 做数据优化
  • 为保证应用的可用性,使用 componentDidCatch 来处理

# 今日解答:

# 一,React16 废弃的生命周期和新的生命周期

    1. React16 废弃的三个生命周期有 3 个 will: componentWillMount, componentWillReceiveProps, componentWillUpdate。 废弃的原因是,在 React16 的 Fiber 架构中,调和过程会多次执行 will 周期,不再是一次执行,失去了原有的意义,此外,多次执行,在生命周期中如果有 setState 活 dom 操作,会触发多次重绘,影响性能,也会导致数据错乱。
    • componentWillReceiveProps
      • i. 在 props 变化时触发
      • ii. 在父组件导致子组件的 rerender 时,即使 props 没有变化,也触发【componentWillReceiveProps 的设计本身就存在问题】
    1. Reactt16 的新增的两个生命周期 getDerivedStateFromProps, getSnapshotBeforeUpdate
    • getDerivedStateFromProps的用法
      • 触发频繁,无论 state 还是 props 变化,都会触发
      • 不能 setState,而是返回一个对象来更新 state,使用不便,也可能触发多次状态更新
    • getSnapshotBeforeUpdate
      • 在 render 之后,更新 dom 之前,state 已更新,可以用来读取 dom,强制用户只能在 mount 阶段读取 dom
      • getSnapshotBeforeUpdate 这个周期在 Fiber 架构中,只会调用一次,实现了类似 willMount 的效果

# 二:React16 的三大特性

  • TimeSlicing【时间切片】
    • 为解决 CPU 速度问题,React 在 render 的时候,不会阻塞现在的线程
    • 简单来说,react 的异步渲染其实是拉长了 render 的时间,一次跑一点,所以机器性能很差的时候,react 渲染只会有稍微的延迟,而不是卡顿
  • Suspense 【悬停】
    • 主要解决网络的 IO 问题
    • 调用render函数->发现有异步请求->悬停,等待异步请求结果->再渲染展示数据
    /// suspense之前
    function MovieDetails(props) {
      const movie = movieDetailsJSON[props.id];
      return (
        <div className="MovieDetails">
          <MoviePoster src={movie.poster} />
          <h1>{movie.title}</h1>
          <MoviesMetrics {...movie} />
        </div>
      );
    }
    /// Suspense做法
    const movieDetailsFetcher = createFetcher(fetchMovieDetails);
    function MovieDetails(props) {
      const movie = movieDetailsFetcher.read(props.id);
      return (
        <div className="MovieDetails">
          <MoviePoster src={movie.poster} />
          <h1>{movie.title}</h1>
          <MoviesMetrics {...movie} />
        </div>
      );
    }
    
    1. 添加了 componentDidCatch,可以友好的展示 fallback 组件,可以捕捉到它的子元素(包括嵌套子元素)抛出的异常;可以复用错误组件。

# React16.8

  • 加入 hooks,让 react 函数式组件更加灵活
    • hooks 之前,React 存在很多问题
      • a. 组件间复用状态逻辑困难
      • b. 复杂组件难以理解,高阶组件和函数组件的嵌套过深
      • c. class 组件的 this 指向问题
      • d. 难以记忆的生命周期
    • 常用的 hooks
      • useState 返回有状态的值,以及更新这个状态值的函数
      • useEffect 接受包含命令式,可能有副作用代码的函数
      • useContext 接受上下文对象(从 React.createContext 返回的值),并返回当前上下文值
      • useReducer userState 的替代方案,接受类型为(state, action)=> newState 的 reducer,并返回 dispatch 方配对当前状态
      • useCallback, 返回一个回忆的 memoized 版本
      • useMemo 纯的记忆函数
      • useRef 返回一个可变的 ref 对象,其.current 属性被初始化为传递的参数,返回的 ref 对象在组件的整个生命周期内保持不变
      • useImperativeMethods 自定义使用 ref 时公开给父组件的实例值
      • useMutationEffect 更新兄弟组件之前,它在 React 执行其 DOM 改变的同一阶段同步触发
      • useLayoutEffect Dom 改变后同步触发,使用它来从 DOM 读取布局并同步重新渲染

# react16.9

    1. 重命名 Unsafe 生命周期,改为 UNSAFE_
    1. 废弃javascript:形式的 URL,以JavaScript:开头的 URL 容易遭受攻击,造成安全漏洞
    1. 废弃 Factory 组件
    1. act()支持异步函数,可以在调用它的时候使用 await
    1. <React.Profiler>进行性能评估

# React16.13.0

    1. 支持在渲染期间调用 setState,但仅适用于同一组件
    1. 可检测冲突的样式规则并记录警告
    1. 废弃 unstatble_createPortal,并使用 createPortal
    1. 将组件堆栈添加到开发警告中,使开发人员能够隔离 bug 并进行调试程序