React生命周期钩子函数有哪些(通俗易懂地详解React生命周期)

什么是生命周期方法?新的 React16+ 生命周期方法是怎样的?你该如何直观地理解它们,以及为什么它们很有用?

React 组件都有自己的阶段。

如果要你“构建一个 Hello World 组件”,我相信你会这么做:

class HelloWorld extends React.Component {
 render() {
 return 

 Hello World 

   } }

在客户端渲染这个组件时,你最终可能会看到如下的视图:

在呈现这个视图之前,这个组件经历了几个阶段。这些阶段通常称为组件生命周期。

对于人类而言,我们会经历小孩、成人、老人阶段。而对于 React 组件而言,我们有挂载、更新和卸载阶段。

巧合的是,挂载一个组件就像将一个新生婴儿带到这个世界。这是组件第一次拥有了生命。组件正是在这个阶段被创建,然后被插入到 DOM 中。

这是组件经历的第一个阶段――挂载阶段。

但它并不会就这样结束了。React 组件会“成长”,或者说组件会经历更新阶段。

如果 React 组件不经历更新阶段,它们将保持被创建时的状态。

大部分组件会被更新――无论是通过修改 state 还是 props,也就是经历更新阶段。

组件经历的最后一个阶段是卸载阶段。

在这个阶段,组件会“死亡”。用 React 术语来描述,就是指从 DOM 中移除组件。

这些就是你需要了解的有关组件生命周期的一切。

对了,React 组件还需要经历另一个阶段。有时候代码会无法运行或者某处出现了错误,这个时候组件正在经历错误处理阶段,就像人类去看医生。

现在,你了解了 React 组件的四个基本阶段或者说生命周期。

  1. 挂载――组件在这个阶段被创建然后被插入到 DOM 中;

  2. 更新――React 组件“成长”;

  3. 卸载――最后阶段;

  4. 错误处理――有时候代码无法运行或某处出现了错误。

注意:React 组件可能不会经历所有阶段。一个组件有可能在挂载后立即就被卸载――没有更新或错误处理。

了解组件经历的各个阶段只是整个等式的一部分,另一部分是了解每个阶段所对应的方法。

这些方法就是众所周知的组件生命周期方法。

让我们来看看这 4 个阶段所对应的方法。

我们先来看一下挂载阶段的方法。

挂载阶段是指从组件被创建到被插入 DOM 的阶段。

这个阶段会调用以下几个方法(按顺序描述)。

1. constructor()

这是给组件“带来生命”时调用的第一个方法。

在将组件挂载到 DOM 之前会调用 constructor 方法。

通常,你会在 constructor 方法中初始化 state 和绑定事件处理程序。

这是一个简单的例子:

const MyComponent extends React.Component {
 constructor(props) {
 super(props) 
 this.state = {
 points: 0
 } 
 this.handlePoints = this.handlePoints.bind(this) 
 } 
}

我相信你已经很熟悉这个方法了,所以我不打算进一步再做解释。

需要注意的是,这是第一个被调用的方法――在组件被挂载到 DOM 之前。

2. static getDerivedStateFromProps()

在解释这个生命周期方法之前,我先说明如何使用这个方法。

这个方法的基本结构如下所示:

const MyComponent extends React.Component {
 ... 
 static getDerivedStateFromProps() {
 //do stuff here
 } 
}

这个方法以 props 和 state 作为参数:

... 
 static getDerivedStateFromProps(props, state) {
 //do stuff here
 } 
...

你可以返回一个用于更新组件状态的对象:

... 
 static getDerivedStateFromProps(props, state) { 
 return {
 points: 200 // update state with this
 }
 } 
 ...

或者返回 null,不进行更新:

... 
 static getDerivedStateFromProps(props, state) {
 return null
 } 
...

你可能会想,这个生命周期方法很重要吗?它是很少使用的生命周期方法之一,但它在某些情况下会派上用场。

请记住,这个方法在组件被初始挂载到 DOM 之前调用。

下面是一个简单的例子:

假设有一个简单的组件,用于呈现足球队的得分。

得分被保存在组件的 state 对象中:

class App extends Component {
 state = {
 points: 10
 }
 render() {
 return (
 
 
 
 

 You've scored {this.state.points} points.  

   
 );  } }

结果如下所示:

源代码可以在 GitHub 上获得:

https://github.com/ohansemmanuel/points

假设你像下面这样在 static getDerivedStateFromProps 方法中放入其他分数,那么呈现的分数是多少?

class App extends Component {
 state = {
 points: 10
 }
 // *******
 // NB: Not the recommended way to use this method. Just an example. Unconditionally overriding state here is generally considered a bad idea
 // ********
 static getDerivedStateFromProps(props, state) {
 return {
 points: 1000
 }
 }
 render() {
 return (
 
 
 
 

 You've scored {this.state.points} points.  

   
 );  } }

现在我们有了 static getDerivedStateFromProps 组件生命周期方法。在将组件挂载到 DOM 之前这个方法会被调用。通过返回一个对象,我们可以在组件被渲染之前更新它的状态。

我们将看到:

1000 来自 static getDerivedStateFromProps 方法的状态更新。

当然,这个例子主要是出于演示的目的,static getDerivedStateFromProps 方法不应该被这么用。我这么做只是为了让你先了解这些基础知识。

我们可以使用这个生命周期方法来更新状态,但并不意味着必须这样做。static getDerivedStateFromProps 方法有它特定的应用场景。

那么什么时候应该使用 static getDerivedStateFromProps 方法呢?

方法名 getDerivedStateFromProps 包含五个不同的单词:“Get Fromived State From Props”。

顾名思义,这个方法允许组件基于 props 的变更来更新其内部状态。

此外,以这种方式获得的组件状态被称为派生状态。

根据经验,应该谨慎使用派生状态,因为如果你不确定自己在做什么,很可能会向应用程序引入潜在的错误。

3. render()

在调用 static getDerivedStateFromProps 方法之后,下一个生命周期方法是 render:

class MyComponent extends React.Component {
 // render is the only required method for a class component 
 render() {
 return 

 Hurray! 

 } }

如果要渲染 DOM 中的元素,可以在 render 方法中编写代码,即返回一些 JSX。

你还可以返回纯字符串和数字,如下所示:

class MyComponent extends React.Component {
 render() {
 return "Hurray" 
 }
}

或者返回数组和片段,如下所示:

class MyComponent extends React.Component {
 render() {
 return [
 Hello
,   World