React開發——step2 react16.3生命周期的更改和一些实践注意

我总以为react就像一个状态机,它提供的生命周期让我可以在某个特定时间作特定的事情,获得我想要的结果。react

react16.3对生命周期的upgrade

React16打算废弃的三个生命周期函数后端

  • componentWillMount
  • componentWillReceiveProps
  • componentWillUpdate

官方说法是:官方计划在17版本彻底删除这三个函数,只保留UNSAVE_前缀的三个函数,目的是为了向下兼容,可是对于开发者而言应该尽可能避免使用他们,而是使用新增的生命周期函数替代它们数组

取而代之的是两个新的生命周期函数dom

  • static getDerivedStateFromProps
  • getSnapshotBeforeUpdate

生命周期概述

constructor
  1. 用于初始化内部状态
  2. 惟一能够直接修改state的地方(不须要setState)
getSnapshotBeforeUpdate
  1. 在页面render以前调用
  2. 典型场景:在render以前,获取上一次render的dom状态
getDerivedStateFromProps
  1. 当state须要从props初始化时使用
  2. 每次render都会调用
  3. 典型场景: 表单控件从父组件获取默认值
  4. 注意事项: 官方不推荐常常使用
componentDidMount
  1. UI渲染完成后调用
  2. 只执行一次
  3. 典型场景: 获取外部数据
componentWillUnMount
  1. 组件被移除时调用
  2. 典型场景:资源释放

详谈sholudComponentUpdate

shouldComponentUpdate(nextProps, nextState)

shouldComponentUpdate是pureComponent里面实现的方法,它用于比较属性的值有没有发生改变,若是没有的话就不render了。
也就是说
component: 能够本身实现shouldComponentUpdate
pureComponent:已经帮咱们实现了,要注意是浅比较。ide

这里因为arr是一个引用数据类型,它的地址没有发生改变,因此咱们的PureComponent是不会触发render的。你能够把PureComponent改为component就会发现可以re-render.函数

import React, { PureComponent, Component } from 'react';

class IndexPage extends PureComponent {
  constructor() {
    super();
    this.state = {
      arr:['1']
    };
    console.log('constructor');
  }

  changeState = () => {
    let { arr } = this.state;
    arr.push('2');
    console.log(arr);
    this.setState({
      arr
    })
  };
  
  render() {
    // if the component was extended by the component, it will re-render each time you click
    // if the component was extended by the purecomponent, it won't re-render if the value didn't change
    // if the value is an array, the location of arr doesn't change means the value doesn't change
    console.log('render'); 
    return (
      <div>
        <button onClick={this.changeState}>点击</button>
        <div>
          {this.state.arr.map((item) => {
            return item;
          })}
        </div>
      </div>
    );
  }
}

export default IndexPage

固然,咱们能够比较轻松地解决这个问题,就是new一个数组来赋值。this

this.setState({
      arr: [...arr] // create a new array, so it would re-render
  })

我认为比较好的方式是:父组件用PureComponent, 子组件用Component,保证子组件可以follow父组件的变化。spa

一点疑惑: 从后端获取数据 componentWillMount vs componentDidMount

首先对比一下两个生命周期获取数据的区别:
componentWillMount获取数据:code

componentWillMount:
1. 执行willMount函数,等待数据返回component

2. 执行render函数

3. 执行didMount函数

4. 数据返回, 执行render

componentDidMount:
1. 执行willMount函数

2. 执行render函数

3. 执行didMount函数, 等待数据返回

4. 数据返回, 执行render
看起来,咱们在componentWillMount里面获取数据是能够更节约时间的。
关于为何废弃它, 官方说法是这样的:

UNSAFE_componentWillMount() is invoked just before mounting occurs. It is called before render(), therefore calling setState() synchronously in this method will not trigger an extra rendering. Generally, we recommend using the constructor() instead for initializing state.

Avoid introducing any side-effects or subscriptions in this method. For those use cases, use componentDidMount() instead.

side-effects说的多是:

  1. 若是使用服务端渲染的话,willMount会在服务端和客户端各自执行一次,这会致使请求两次(接受不了~),而didMount只会在客户端进行。
  2. 在Fiber以后, 因为任务可中断,willMount可能会被执行屡次。

节省一次render时间,我想若是咱们在render里面判断数据没有ready返回null或者一个Loading图片,也是能够作到的。

相关文章
相关标签/搜索