[TOC]
# Understanding React lifecycle methods
# 理解React生命周期方法
React provides methods to handle the data during the lifecycle of a component. This is very useful when we need to update our application at particular times.
React提供的方法是在组件的生命周期内处理数据。当我们需要在特定时间更新应用程序时,这非常有用。
![React 生命周期](https://img.kancloud.cn/dd/5a/dd5aa4f307557b6e84e02578f32733e4_488x636.png)
# 介绍
**所谓的生命周期就是React中定制的一套执行函数的顺序**
分为三个阶段,每一个阶段都有不同的函数执行顺序,值得注意的是实例化和销毁阶段执行一次,存在期是可以反复执行的:
1、组件**实例化阶段**
(在实例化阶段只会执行一次)
`constructor`
`componentWillMount`
`render`
`componentDidMount`
2、组件**存在阶段**
(在组件存在的阶段,每重新渲染一次,都会执行一遍)
`componentWIllReceiveProps`
`shouldComponentUpdate`(特别注意,如果返回`false`,则不会执行渲染,也会跳过`render`前后的钩子函数)
`componnetWillUpdate`
`render`
`componentDidUpdate`(渲染之后,可以通过`ref`或者`findDOMNode`,来操作 DOM,当 React 运行在服务端是,不会被调用)
3、组件**销毁阶段**
`componentWIllUnmount`
React 组件的生命周期,已经说忘了,那么我们需要看一下,贯穿整个生命周期的`state`和`props`是什么情况。
首先要明白:React 的数据流是单向的。
## 详解
```js
constructor (构造函数)
```
只有在组件实例化并插入到 DOM 中的时候才会被调用。组件实例 化的过程称作组件的挂载(mount)。
它在组件初始化时被调用。在这个方法中,你可以设置初始化状态以及绑定类方法。
```js
componentWillMount()
```
它在`render()`方法之前被调用。**这就是为什么它可以用作去设置组件内部的状态**,因为它不会触发组件的再次渲染。但一般来说,**还是推荐在`constructor()`中去初始化状态**。
```js
render()
```
该方法会在组件被挂载过程中被调用,同时当组件被更新的时候也会被调用,每当组件的状态 (state)或属性 (props)改变时,组件的 `render()` 方法都会被调用
这个生命周期方法是必须有的,它返回作为组件输出的元素。这个方法应该是一个纯函数,因此不应该在这个方法中修改组件的状态。它把属性和状态作为输入并且返回(需要渲染的)元素
```js
componentDidMount()
```
它仅在组件挂载后执行一次。**这是发起异步请求去 API 获取数据的绝佳时期**。获取到的数据将被保存在内部组件的状态中然后在 `render()` 生命 周期方法中展示出来。
```js
componentWillReceiveProps(newProps)
```
这个方法在一个更新生命周期(updatelifecycle) 中被调用。新的属性会作为它的输入。因此你可以利用 `this.props` 来对比之后的属性和之前的属性,基于对比的结果去实现不同的行为。此外,你可以基于新的属性 来设置组件的状态。
```js
shouldComponentUpdate(newProps, newState)
```
每次组件因为状态或者属性更改而更新时,它都会被调用。你将在成熟的 React 应用中使用它来进行性能优化。在一个 更新生命周期中,组件及其子组件将根据该方法返回的布尔值( true/false )来决定是否重新渲染。 这样你可以阻止组件的渲染生命周期(render lifecycle)方法,避免不必要的渲染。**注意在这个生命周期方法中你不能再触发`setState()`**。
例如 React 中的就提供了一个 `PureComponent` 的类,当我们的组件继承于它时,组件更新时就会**默认先比较新旧属性和状态**,从而决定组件是否更新。值得注意的是,`PureComponent` 进行的是**浅比较**,所以组件状态或属性改变时,都需要返回一个新的对象或数组
```js
componentWillUpdate(nextProps, nextState)
```
这个方法是 `render()` 执行之前的最后 一个方法。你已经拥有下一个属性和状态,它们可以在这个方法中任由你处置。你可以利用这个方法在渲染之前进行最后的准备。**注意在这个生命周期方法中你不能再触发`setState()`**。如果你想基于新的属性计算状态,你必须利用 `componentWillReceiveProps()`。
```js
componentDidUpdate(prevProps, prevState)
```
这个方法在 `render()` 之后立即调用。你可以用它当成操作 DOM 或者执行更多异步请求的机会。
```js
componentWillUnmount()
```
它会在组件销毁之前被调用。你可以利用这个生命周期 方法去执行任何清理任务。
```js
componentDidCatch(error, info)
```
错误处理,它在 React 16 中引入,用来 捕获组件的错误。举例来说,在你的应用中展示样本数据本来是没问题的。但是可能会有列表的本地状态被意外设置成 `null` 的情况发生(例如从外部 API 获取列表失败时,你把本 地状态设置为空了)。然后它就不能像之前一样去过滤(filter)和映射(map)这个列表,使用真实的 API因为它不是一个空列表(`[]`)而是 `null`。这时组件就会崩溃,然后整个应用就会挂掉。现在你可以用 `componentDidCatch()` 来捕获错误,将它存在本地的状态中,然后向用户展示一条信息,说明应用发生了错误。
> 注意⚠️:新版本的中的生命周期有所变动![---高级特性---](../---%E9%AB%98%E7%BA%A7%E7%89%B9%E6%80%A7---.md)
# 参考
[图解 ES6 中的 React 生命周期](https://juejin.im/post/5a062fb551882535cd4a4ce3)
[setState详解](https://blog.csdn.net/sysuzhyupeng/article/details/63250741)
https://blog.csdn.net/Donspeng/article/details/76662664
https://blog.csdn.net/ytongc/article/details/79182161