react的生命周期函数

生命周期

生命周期函数是指在某一个时刻会自动执行的函数

react v16.3 版本中。在这次的更新中,新引入的两个生命周期函数 getDerivedStateFromProps,getSnapshotBeforeUpdate 以及在未来 v17.0 版本中,即将被移除的三个生命周期函数

componentWillMount,
componentWillReceiveProps,
componentWillUpdate。

react v16.3最大的变动莫过于生命周期去掉了以下三个

componentWillMount
componentWillReceiveProps
componentWillUpdate

同时为了弥补失去上面三个周期的不足又加了两个

static getDerivedStateFromProps
getSnapshotBeforeUpdate

当然,这个更替是缓慢的,在整个16版本里都能无障碍的使用旧的三生命周期,但值得注意的是,旧的生命周期(unsafe)不能和新的生命周期同时出现在一个组件,否则会报错“你使用了一个不安全的生命周期”。

为什么要改

旧的生命周期十分完整,基本可以捕捉到组件更新的每一个state/props/ref,没有什从逻辑上的毛病。

但是架不住官方自己搞事情,react打算在17版本推出新的Async Rendering,提出一种可被打断的生命周期,而可以被打断的阶段正是实际dom挂载之前的虚拟dom构建阶段,也就是要被去掉的三个生命周期。生命周期一旦被打断,下次恢复的时候又会再跑一次之前的生命周期,因此componentWillMount,componentWillReceiveProps, componentWillUpdate都不能保证只在挂载/拿到props/状态变化的时候刷新一次了,所以这三个方法被标记为不安全。

两个新生命周期

static getDerivedStateFromProps

触发时间:在组件构建之后(虚拟dom之后,实际dom挂载之前) ,以及每次获取新的props之后。每次接收新的props之后都会返回一个对象作为新的state,返回null则说明不需要更新state。配合componentDidUpdate,可以覆盖componentWillReceiveProps的所有用法

class Example extends React.Component {
  static getDerivedStateFromProps(nextProps, prevState) {
      // 没错,这是一个static
  }
}

getSnapshotBeforeUpdate

触发时间: update发生的时候,在render之后,在组件dom渲染之前。返回一个值,作为componentDidUpdate的第三个参数。配合componentDidUpdate, 可以覆盖componentWillUpdate的所有用法。

class Example extends React.Component {
  getSnapshotBeforeUpdate(prevProps, prevState) {
    // ...
  }
}

react处理要点

初始化state — Initializing state

在constructor初始化state数据

请求数据 — Fetching external data

在componentDidMount请求异步加载的数据有一种错觉,在componentWillMount请求的数据在render就能拿到,但其实render在willMount之后几乎是马上就被调用,根本等不到数据回来,同样需要render一次“加载中”的空数据状态,所以在componentDidMount去取数据几乎不会产生影响。而且componentDidMount值执行一次。

添加事件监听 — Adding event listeners (or subscriptions)

在componentDidMount中添加加事件监听
react只能保证componentDidMount-componentWillUnmount成对出现,componentWillMount可以被打断或调用多次,因此无法保证事件监听能在unmount的时候被成功卸载,可能会引起内存泄露

根据props更新state — Updating state based on props

用getDerivedStateFromProps(nextProps, prevState), 将传入的props更新到state上
用来代替componentWillReceiveProps(nextProps, nextState),willReceiveProps经常被误用,导致了一些问题,因此该方法将不被推荐使用。
getDerivedStateFromProps是一个static方法,意味着拿不到实例的this,所以想要在setState之前比对一下props有没有更新,下面方法是不能用了

if (this.props.currentRow !== nextProps.currentRow) {
...
}

取而代之的是,额外写一个state来记录上一个props (` ^ ‘)

if (nextProps.currentRow !== prevState.lastRow) {
  return {
    ...
      lastRow: nextProps.currentRow,
  };
  // 不更新state
  return null
}

为什么我们不给一个prevProps参数呢,官方解释是,一来prevProps第一次被调用的时候是null,每次更新都要判断耗性能,二来如果大家都习惯了,以后react不记录prevProps的话(啥),可以省下不少内存
触发请求 — Invoking external callbacks

在更新前记录原来的dom节点属性 — Reading DOM properties before an update

在upate之前获取dom节点,getSnapshotBeforeUpdate(prevProps, prevState)代替componentWillUpdate(nextProps, nextState)
getSnapshotBeforeUpdate在render之后,但在节点挂载前
componentDidUpdate(prevProps, prevState, snapshot)直接获得getSnapshotBeforeUpdate返回的dom属性值

生命周期功能替换一览

static getDerivedStateFromProps(nextProps,prevState) {
    // 触发时间:在组件构建之后(虚拟dom之后,实际dom挂载之前) ,以及每次获取新的props之后。
    // 每次接收新的props之后都会返回一个对象作为新的state,返回null则说明不需要更新state.
    // 配合componentDidUpdate,可以覆盖componentWillReceiveProps的所有用法

     <!--用getDerivedStateFromProps(nextProps, prevState), 将传入的props更新到state上用来代替componentWillReceiveProps(nextProps, nextState),
willReceiveProps经常被误用,导致了一些 问题,因此该方法将不被推荐使用。getDerivedStateFromProps是一个static方法,意味着拿不到实例的this,
所以想要在setState之前比对一下props有没有更新-->

    4. Updating state based on props
    7. Fetching external data when props change
  }
  constructor() {
    //页面挂载之后立马执行
    1. Initializing state
  }
  componentWillMount() {
    // 要被废弃
    // 1. Initializing state
    // 2. Fetching external data
    // 3. Adding event listeners (or subscriptions)
  }
  componentDidMount() {
    <!--组件被挂在页面上后会自动执行 在render函数之后执行 而且只会在挂在的时候执行-->
    2. Fetching external data
    3. Adding event listeners (or subscriptions)
  }
  componentWillReceiveProps() {
    // 要被废弃
    // 4. Updating state based on props
    // 6. Side effects on props change
    // 7. Fetching external data when props change
  }
  shouldComponentUpdate(nextProps,nextState) {
    <!--组件被更新之前会执行该函数 改函数要求返回一个布尔值-->
    <!--如果返回true组件则更新,反之不更新-->
    <!--可以利用上面的两个参数来判断是否执行该函数 比如上面的todolist中
    TodoItem.js中的父组件向子组件传递input框内content,可以判断如下-->
    if(nextProps.content !== this.props.content) { // 该方法市常常用来提高效率
      return true
    } else {
      return false 
      // 这样就避免了在input框输入的过程中,反复渲染子组件(即执行render函数),从而提高了效率。
    }
  }
  componentWillUpdate(nextProps, nextState) {
     // 要被废弃
    // 5. Invoking external callbacks
    // 8. Reading DOM properties before an update
    
  }
  render() {
    //页面挂载 state props改变时 会自动刷新
    <!--组件中这个函数一定会执行,否则组件无法挂在-->
    <!--其他函数可以没有-->
  }
  getSnapshotBeforeUpdate(prevProps, prevState) {
      <!-- 触发时间: update发生的时候,在render之后,在组件dom渲染之前。
      返回一个值,作为componentDidUpdate的第三个参数。
      配合componentDidUpdate, 可以覆盖componentWillUpdate的所有用法。-->
    8. Reading DOM properties before an update
  }
  componentDidUpdate(prevProps, prevState, snapshot) {
    //在组件更新完成之后 调用该函数
    5. Invoking external callbacks
    6. Side effects on props change
  }
  
  componentWillUnmount() {
    <!--在组件销毁之前调用-->
  }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 作为一个合格的开发者,不要只满足于编写了可以运行的代码。而要了解代码背后的工作原理;不要只满足于自己的程序...
    六个周阅读 12,692评论 1 33
  • 一、生命周期函数的定义 在某个时刻自动被调用的函数是生命周期函数 二、React中生命周期函数示意图 三、生命周期...
    灯光树影阅读 5,998评论 0 1
  • React 官方正式发布了 v16.3 版本。在这次的更新中,除了前段时间被热烈讨论的新 Context API之...
    固执的坚持己见阅读 5,847评论 0 4
  • 生命周期流程图简单如下: 组件让你把用户界面分成独立的,可重复使用的部分,并且将每个部分分开考虑。React.Co...
    Simple_Learn阅读 4,736评论 0 0
  • 今天是520,也只能写写情感,做为一个三十岁还没结婚的人(也没对象),对于感情只想谈谈当下个人的恋爱观了,...
    自然而不语阅读 3,265评论 2 2