React16时期,该用什么姿态写 React ?

React16 后的各功用点是多个版本陆陆续续迭代增添的,本篇文章的解说是建立在
16.6.0 版本上

本篇文章主旨在引见 React16 今后版本中新增或修正的处所,所以关于 React16 之前版本的功用,本篇文章看成您已充足了解了,不再赘述

更新概览

从 React v16.0 ~ React v16.6 的更新概览(只触及部份经常运用api):

  • React v16.0
  1. render支撑返回数组和字符串
  2. 支撑自定义 DOM 属性
  3. 削减文件体积
  • React v16.3
  1. createContext
  2. createRef
  3. 性命周期函数的更新
  • React v16.4

更新 getDerivedStateFromProps

  • React v16.6
  1. memo
  2. lazy
  3. Suspense
  4. static contextType
  5. static getDerivedStateFromError
  • React v16.7(~Q1 2019)

Hooks

接下来将针对影响较大,运用频次较高的更新点逐一解说。

纯函数的PureComponent

我们晓得,对 React 组件的机能优化,shouldComponentUpdate函数是很重要的一啪,所以 React 才会在 React.Component的基础上增添了React.PureComponent,然则关于非class类的纯函数写法,却没法增添如许的便利处置惩罚。
关于这个题目,React16.6 增添了React.memo这个高阶组件

平常运用体式格局:

const C = React.memo(props => {
  // xxx
})

React.memo的完成相似React.PureComponent,所以它内部是对对象举行浅比较。
React.memo许可你自定义比较要领,以下:

// 函数的返回值为 true 时则更新组件,反之则不更新
const equalMethod = (prevProps, nextProps): boolean => {
  // 定义你的比较逻辑
}
const C = React.memo(props => {
  // xxx
}, equalMethod)

新的性命周期函数是如何的

React性命周期分为三个阶段:挂载、更新、卸载,React16后又多了一个非常,我们逐一看下。
《React16时期,该用什么姿态写 React ?》

挂载

性命周期的实行递次

  1. constructor
  2. static getDerivedStateFromProps
  3. render
  4. componentDidMount

rendercomponentDidMount较 React16 之前无变化。关于挂载历程,我们偏重看下constructorcomponentWillMountstatic getDerivedStateFromProps

constructor

  1. 初始化 state
    注重:应防止运用propsstate赋值,如许的话, state的初始化能够提到constructor表面处置惩罚
constructor(props) {
  super(props);
  this.state = {
    x: 1,
    // y: props.y, // 防止如许做,背面我们会讲应当如何处置惩罚
  }
}
  1. 给要领绑定this
constructor(props) {
  super(props);
  this.handleClick = this.handleClick.bind(this);
}

然则,以上两件事放到constructor表面处置惩罚会更简朴些,以下:

class C extends React.Component {
  state = {
    x: 1
  }
  handleClick = (e) => {
    // xxx
  }
}

所以,React16 今后用到constructor的场景会变少。

componentWillMount

能够看到,componentWillMount在 React16 中被“删掉”了(如许说实际上是有题目的,由于 React 并未真正删除该性命周期函数,只是申饬开发者,该函数在将来版本中会被烧毁掉),那末题目就涌现了,原本在这个性命周期中的做的事变,如今该放到那里去做呢?

起首问本身一个题目,原本的时刻都在这个性命周期里做什么?答案是大部份时刻会在这里做 AJAX 要求,然后实行setState从新衬着。

然而在componentWillMount里做 AJAX 要求着实不是一个明智之举,由于关于同构项目中,componentWillMount是会被挪用的。

还有人会在这内里初始化state,关于state的初始化,请参看楼上小节。

综上所述,componentWillMount实在原本没有什么重要作用,假如你的代码范例,去掉的话,不会对如今的项目发生什么影响。

static getDerivedStateFromProps

上面我们讲到,应防止运用propsstate赋值,然则在 React16 前我们都是这么做的,如今假如不让这么操作了,那该在那里处置惩罚这块逻辑呢? React16 给出的答案就是 static getDerivedStateFromProps
挂载组件时,该静态要领会在render前实行;更新组件时,该静态要领会在shouldComponentUpdate前实行。

class C extends React.Component {
  state = {
    y: 0
  }
  static getDerivedStateFromProps(props, state): State {
    if(props.y !== state.y) {
      return {
        y: props.y
      };
    }
  }
}

getDerivedStateFromProps的返回值将作为setState的参数,假如返回null,则不更新state,不能返回object 或 null 之外的值,否则会正告。

getDerivedStateFromProps是一个静态要领,是拿不到实例this的,所以开发者应当将该函数设想成纯函数。

如许,有无发明componentWillReceiveProps也就没有用武之地了?是的,React16 把它也“删掉”了(如许说实际上是有题目的,由于 react 并未真正删除该性命周期函数,只是申饬开发者,该函数在将来版本中会被烧毁掉,发起运用更好的getSnapshotBeforeUpdategetDerivedStateFromProps

更新

性命周期函数的实行递次

  1. static getDerivedStateFromProps
  2. shouldComponentUpdate
  3. render
  4. getSnapshotBeforeUpdate
  5. componentDidUpdate

static getDerivedStateFromProps前面已引见过了,而其他的几个性命周期函数与 React16 之前基础无异,所以这里重要引见下getSnapshotBeforeUpdate

getSnapshotBeforeUpdate

在 React 更新 DOM 之前挪用,此时state已更新;
返回值作为componentDidUpdate的第3个参数;
平常用于猎取render之前的 DOM 数据

语法:

class C extends React.Component {
  getSnapshotBeforeUpdate (prevProps, prevState): Snapshot {
    
  }
  componentDidUpdate(prevProps, prevState, snapshot) {
    // snapshot 是从 getSnapshotBeforeUpdate 的返回值,默许是 null
  }
}

getSnapshotBeforeUpdate 的运用场景平常是猎取组建更新之前的滚动条位置。

卸载

componentWillUnmount

较之前无变化。

非常

componentDidCatch 这个函数是 React16 新增的,用于捕捉组件树的非常,假如render()函数抛出毛病,则会触发该函数。能够根据 try catch 来明白和运用,在能够涌现毛病的处所,运用封装好的包括 componentDidCatch 性命周期的组建包裹能够失足的组件。

class PotentialError extends React.Component {
  state = {
    error: false,
  }
  componentDidCatch(error, info) {
    console.error(info);
    this.setState({
      error
    });
  }
  render() {
    if (this.state.error) {
      return <h1>失足了,请打卡控制台检察细致毛病!</h1>;
    }
    return this.props.children;   
  } 
}

如:

const Demo = () => (
  <PotentialError>
    <div>{{a: 1}}</div>
  </PotentialError>
)

如许,Demo 组件纵然直接运用对象作为子组件也不会报错了,由于被 PotentialError 接收了。

新性命周期的完全demo

看看穿上新性命周期这身新衣服后的模样吧

import React from 'react'

export default class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    // 初始化state体式格局(1)
    this.state = {

    }
  }
    
  static defaultProps = {

  }

  // 初始化state体式格局(2)
  state = {

  }
  static getDerivedStateFromProps(props, state) {
    return state
  }
  componentDidCatch(error, info) {

  }
  render() {

  }
  componentDidMount() {

  }
  shouldComponentUpdate(nextProps, nextState) {
    
  }
  getSnapshotBeforeUpdate(prevProps, prevState) {

  }
  componentDidUpdate(prevProps, prevState, snapshot) {

  }
  componentWillUnmount() {

  }

}

Suspense

Hooks

time slicing

【未完待续】

    原文作者:小贼先生
    原文地址: https://segmentfault.com/a/1190000018341891
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞