React 生命周期:方法和钩子解释 The React lifecycle: methods and hooks explained

React component undergoes three different phases in its lifecycle, including mounting, updating, and unmounting. Each phase has specific methods responsible for a particular stage in a component's lifecycle. These methods are technically particular to class-based components and not intended for functional components.
React 组件在其生命周期中经历三个不同的阶段,包括安装、更新和卸载。每个阶段都有特定的方法负责组件生命周期中的特定阶段。这些方法在技术上特定于基于类的组件,不适用于功能组件。

However, since the concept of Hooks was released in React, you can now use abstracted versions of these lifecycle methods when you’re working with functional component state. Simply put, React Hooks are functions that allow you to “hook into” a React state and the lifecycle features within function components.
然而,由于 Hooks 的概念是在 React 中发布的,因此当您处理功能组件状态时,您现在可以使用这些生命周期方法的抽象版本。简而言之,React Hooks 是允许您“挂钩”React 状态和函数组件内的生命周期特性的函数。

In this post, you'll learn more about the React component lifecycle and the different methods within each phase (for class-based components), focusing particularly on methods and hooks.
在这篇文章中,您将了解更多关于 React 组件生命周期和每个阶段中的不同方法(对于基于类的组件),特别关注方法和挂钩。

Phases of a React component's lifecycle
React 组件生命周期的阶段

A React component undergoes three phases in its lifecycle: mountingupdating, and unmounting.
React 组件在其生命周期中经历三个阶段:安装、更新和卸载。

  1. The mounting phase is when a new component is created and inserted into the DOM or, in other words, when the life of a component begins. This can only happen once, and is often called “initial render.”
    安装阶段是在创建新组件并将其插入 DOM 时,或者换句话说,在组件生命周期开始时。这只能发生一次,通常称为“初始渲染”。
  2. The updating phase is when the component updates or re-renders. This reaction is triggered when the props are updated or when the state is updated. This phase can occur multiple times, which is kind of the point of React.
    更新阶段是组件更新或重新渲染的时候。当道具更新或状态更新时,会触发此反应。这个阶段可以发生多次,这就是 React 的意义所在。
  3. The last phase within a component's lifecycle is the unmounting phase, when the component is removed from the DOM.
    组件生命周期的最后一个阶段是卸载阶段,即从 DOM 中删除组件。

In a class-based component, you can call different methods for each phase of the lifecycle (more on this below). These lifecycle methods are of course not applicable to functional components because they can only be written/contained within a class. However, React hooks give functional components the ability to use states.
在基于类的组件中,您可以为生命周期的每个阶段调用不同的方法(更多内容见下文)。这些生命周期方法当然不适用于功能组件,因为它们只能编写/包含在一个类中。然而,React hooks 赋予功能组件使用状态的能力。

Hooks have gaining popularity because they make working with React cleaner and often less verbose.
Hooks 越来越受欢迎,因为它们使 React 的工作更干净,而且通常不那么冗长。

React lifecycle methods 反应生命周期方法

Let’s learn more about the methods that make up each of our three phases.
让我们更多地了解构成我们三个阶段的每个阶段的方法。

The mounting phase 安装阶段

In the mounting phase, a component is prepared for and actually inserted into the DOM. To get through this phase, four lifecycle methods are called: constructorstatic getDerivedStateFromPropsrender, and componentDidMount.
在安装阶段,组件准备好并实际插入到 DOM 中。为了度过这个阶段,调用了四个生命周期方法: constructor 、 static getDerivedStateFromProps 、 render 和 componentDidMount 。

The constructor method  constructor 方法

The constructor method is the very first method called during the mounting phase.
constructor 方法是在安装阶段调用的第一个方法。

It's important to remember that you shouldn't add any side effects within this method (like sending an HTTP request) as it's intended to be pure.
重要的是要记住,您不应在此方法中添加任何副作用(如发送 HTTP 请求),因为它是纯粹的。

This method is mostly used for initializing the state of the component and binding event-handler methods within the component. The constructor method is not necessarily required. If you don't intend to make your component stateful (or if that state doesn’t need to be initialized) or bind any method, then it’s not necessary to implement.
此方法主要用于初始化组件的状态和绑定组件内的事件处理程序方法。 constructor 方法不是必需的。如果你不打算让你的组件有状态(或者如果那个状态不需要初始化)或者绑定任何方法,那么就没有必要实现。

The constructor method is called when the component is initiated, but before it’s rendered. It’s also called with props as an argument. It's important you call the super(props) function with the props argument passed onto it within the constructor before any other steps are taken.
constructor 方法在组件启动时被调用,但在它被渲染之前。它也以 props 作为参数调用。在执行任何其他步骤之前,在 constructor 中使用传递给它的 props 参数调用 super(props) 函数很重要。

This will then initiate the constructor of React.Component (the parent of this class-based component) and it inherits the constructor method and other methods of a typical React component.
然后这将启动 React.Component (这个基于类的组件的父级)的 constructor ,它继承了典型 React 组件的 constructor 方法和其他方法。

 

For example, below you can see a class-based component implementation of a counter with a constructor in it, where the state is initialized and an event-handler method is bound (ignore the render method for now):
例如,您可以在下面看到一个基于类的组件实现,其中包含一个 constructor 计数器,其中状态已初始化并绑定了一个事件处理程序方法(暂时忽略 render 方法):

import React from 'react';


class Counter extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            count: 0
        };

        this.setCount = this.setCount.bind(this);
    }

    setCount() {
        this.setState({count: this.state.count + 1});
    }

    render() {
        return (
            <div>
                <h1>Counter</h1>
                <button onClick={this.setCount}>Click to add</button>
                <p>Count: {this.state.count}</p>
            </div>
        )
    }
}

In the Counter component, you can see the component's state is initialized within the constructor method to keep track of the count state. The setCount method, which is an event-handler attached to your button in this case, is bound within the constructor.
在 Counter 组件中,您可以看到组件的状态在 constructor 方法中初始化以跟踪 count 状态。 setCount 方法(在本例中是附加到您的按钮的事件处理程序)绑定在 constructor 中。

The static getDerivedStateFromProps method  static getDerivedStateFromProps 方法
Props and state are completely different concepts, and part of building your app intelligently is deciding which data goes where.
道具和状态是完全不同的概念,智能构建应用程序的一部分是决定哪些数据去哪里。

In many cases though, your component’s state will be derivative of its props. This is where the static getDerivedStateFromProps method comes in. This method allows you to modify the state value with any props value. It's most useful for changes in props over time, and we’ll learn later that it’s also useful in the update phase.
但在许多情况下,你的组件的状态将是它的 props 的派生物。这就是 static getDerivedStateFromProps 方法的用武之地。此方法允许您使用任何 props 值修改 state 值。随着时间的推移,它对 props 的变化最有用,我们稍后会了解到它在更新阶段也很有用。

The method static getDerivedStateFromProps accepts two arguments: props and state, and returns an object, or null if no change is needed. These values are passed directly to the method, so there’s no need for it to have access to the instance of the class (or any other part of the class) and thus is considered a static method.
static getDerivedStateFromProps 方法接受两个参数: props 和 state ,并返回一个对象,如果不需要更改,则返回 null 。这些值直接传递给方法,因此它不需要访问类的实例(或类的任何其他部分),因此被视为静态方法。

In the mounting phase, the getDerivedStateFromProps method is called after the constructor method and right before the component is rendered. This is the most rarely used method in this phase, but it’s still important to know so you can use it if needed.
在安装阶段, getDerivedStateFromProps 方法在构造函数方法之后和组件呈现之前被调用。这是此阶段中最不常用的方法,但了解它仍然很重要,以便您可以在需要时使用它。

For reference, here's an example of how getDerivedStateFromProps is used:
作为参考,下面是如何使用 getDerivedStateFromProps 的示例:

class UserPreview extends React.Component {
    
    constructor(props) {
        super(props);
        this.state = {
            ...
            fullname: ""
        };
    }


    static getDerivedStateFromProps(props, state) {
        return {
            ...
            fullname: `${props.firstname} ${props.lastname}`
        }
    }

    render() {
        // ...
    }
}

Another way of looking at it is just providing a default for your component state based on props.
另一种看待它的方式是根据道具为您的组件状态提供默认值。

The render method  render 方法
The render method is the only required method for a class-based React component. It’s called after the getDerivedStateFromProps method and actually renders or inserts the HTML to the DOM.
render 方法是基于类的 React 组件唯一需要的方法。它在 getDerivedStateFromProps 方法之后调用,并实际呈现或插入 HTML 到 DOM。

Typically, the render method returns the JSX which will eventually be rendered, but it can also return other values.
通常, render 方法返回最终将被渲染的 JSX,但它也可以返回其他值。

It's important to remember that the render method is meant to be pure. This means you can’t modify the state, have any direct interaction with the browser, or any other kind of side effect like sending an HTTP request. Just think of it as writing HTML, but of course as JSX.
重要的是要记住 render 方法是纯粹的。这意味着您无法修改状态、无法与浏览器进行任何直接交互或任何其他类型的副作用,例如发送 HTTP 请求。就把它想象成编写 HTML,但当然是 JSX。

Below is an example of using the render method:
下面是使用 render 方法的示例:

class SubmitButton extends React.Component {
    render() {
        return (
            <button
                type="submit"
                style={this.props.styles}
            >
                {this.props.child}
            </button>
        );
    }
}

The componentDidMount method  componentDidMount 方法
componentDidMount is the last lifecycle method called in the mounting phase. It’s called right after the component is rendered or mounted to the DOM.
componentDidMount 是挂载阶段调用的最后一个生命周期方法。它在组件渲染或安装到 DOM 后立即调用。

With this method, you're allowed to add side effects like sending network requests or updating the component's state. Additionally, the componentDidMount method allows you to make subscriptions like subscribing to the Redux store. You can also call the this.setState method right away; however this will cause a re-render as it kicks in the update phase, since the state has changed.
使用此方法,您可以添加副作用,例如发送网络请求或更新组件的状态。此外, componentDidMount 方法允许您进行订阅,例如订阅 Redux 商店。也可以马上调用 this.setState 方法;然而,这将导致重新渲染,因为它在更新阶段启动,因为状态已经改变。

You need to be careful with componentDidMount because it may cause unnecessary re-renders.
您需要小心使用 componentDidMount ,因为它可能会导致不必要的重新渲染。

Here's an example using the componentDidMount method:
这是使用 componentDidMount 方法的示例:

class NASACounter extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 10
    };
  }

  componentDidMount() {
    const myTimer = setInterval(() => {
      this.state.count > 0
        ? this.setState({ count: this.state.count - 1 })
        : clearInterval(myTimer);
    }, 1000);
  }

  render() {
    return (
      <div style={this.props}>
        <h1>
          NASA Countdown: <br /> {this.state.count || "🪐"} <br />
          {"⭐".repeat(this.state.count) || "🚀"}
        </h1>
        {this.state.count === 0 && <h2>LIFT OFF!!!</h2>}
      </div>
    );
  }
}

A common use case is waiting until a component renders to start an animation, or fetching data from an external source.
一个常见的用例是等待组件呈现以启动动画,或从外部源获取数据。

The updating phase 更新阶段
The Updating phase is triggered when component props or state change, and consists of the following methods: static getDerivedFromProps, shouldComponentUpdate, render, getSnapshotBeforeUpdate, and componentDidUpdate.
Updating 阶段在组件 props 或 state 发生变化时触发,由以下方法组成: static getDerivedFromProps 、 shouldComponentUpdate 、 render 、 getSnapshotBeforeUpdate 和 componentDidUpdate 。

The methods getDerivedFromProps and render are also part of the mounting phase. Since they’ve been covered previously, this section focuses on the other three methods.
getDerivedFromProps 和 render 方法也是安装阶段的一部分。由于之前已经介绍过它们,因此本节重点介绍其他三种方法。

The static getDerivedStateFromProps  static getDerivedStateFromProps
In the update phase, the first lifecycle method called is getDerivedStateFromProps. This method is useful if you have updated props and you want to reflect that in the component's state.
在更新阶段,调用的第一个生命周期方法是 getDerivedStateFromProps 。如果您更新了 props 并且您希望在组件的状态中反映该更新,则此方法很有用。

For instance, a component’s state may depend on the value of its props. With getDerivedStateFromProps, before the component was even re-rendered, its state can reflect those changes and can be shown (if applicable) to the newly updated component.
例如,组件的 state 可能取决于其 props 的值。使用 getDerivedStateFromProps ,甚至在组件被重新渲染之前,它的状态可以反映这些变化,并且可以显示(如果适用)到新更新的组件。

Remember, this method is rarely used and isn’t ideal for most situations.
请记住,此方法很少使用,并且在大多数情况下并不理想。

The shouldComponentUpdate method  shouldComponentUpdate 方法
shouldComponentUpdate is another rarely used lifecycle method. It’s specifically intended for performance optimization, and basically lets you tell React when you don't need to re-render when a new state or props comes in. While it can help avoid re-renders, you shouldn’t rely on it to prevent re-renders since you might skip a necessary update and encounter bugs.
shouldComponentUpdate 是另一种很少使用的生命周期方法。它专门用于性能优化,基本上可以让您在新的 state 或 props 出现时告诉 React 您不需要重新渲染。虽然它可以帮助避免重新渲染,但您不应该依赖在它上面以防止重新渲染,因为您可能会跳过必要的更新并遇到错误。

To prevent renders, you can opt in to logical rendering instead, or use a PureComponent which is recommended by React.
为防止渲染,您可以改为选择逻辑渲染,或使用 React 推荐的 PureComponent 。

This method can accept nextProps and nextState as arguments, however, they’re optional, and you can declare it without the arguments. This method then returns a Boolean value. The Boolean value defines whether a re-render happens. The default value is true, where re-render happens in all cases whenever state or props changes.
此方法可以接受 nextProps 和 nextState 作为参数,但是,它们是可选的,您可以在没有参数的情况下声明它。然后此方法返回一个 Boolean 值。 Boolean 值定义是否发生重新渲染。默认值为 true ,只要 state 或 props 发生变化,所有情况下都会重新渲染。

Note that the shouldComponentUpdate method is ignored when forceUpdate() is invoked.
请注意,调用 forceUpdate() 时将忽略 shouldComponentUpdate 方法。

Here's an example using the shouldComponentUpdate lifecycle method:
下面是一个使用 shouldComponentUpdate 生命周期方法的例子:

class ShowWholeNumber extends React.Component {
    shouldComponentUpdate(nextProps, nextState) {
        return Math.round(nextProps.num) === Math.round(this.props.num);
    }

    render() {
        return (
            <div>
                The Whole number is: {Math.round(this.props.num)}
            </div>
        )
    }
}

The getSnapshotBeforeUpdate method  getSnapshotBeforeUpdate 方法


The getSnapshotBeforeUpdate method gives you access to the previous props and state of the component before it's updated. This allows you to work or check on the previous values of the state or props. It’s another method that’s rarely used.
getSnapshotBeforeUpdate 方法使您可以在更新之前访问组件的前一个 props 和 state 。这允许您处理或检查 state 或 props 的先前值。这是另一种很少使用的方法。

A good use case for this method is handling scroll positions in a chat app. When a new message comes in as the user is viewing old messages, it shouldn’t push the old ones out of view.
这种方法的一个很好的用例是处理聊天应用程序中的滚动位置。当用户正在查看旧消息时出现新消息时,不应将旧消息推出视图。

getSnapshotBeforeUpdate is called after the render method, and before componentDidUpdate. If the getSnapshotBeforeUpdate method returns anything, it will be passed as a parameter for the componentDidUpdate method:
getSnapshotBeforeUpdate 在 render 方法之后和 componentDidUpdate 之前被调用。如果 getSnapshotBeforeUpdate 方法返回任何东西,它将作为参数传递给 componentDidUpdate 方法:

class ChatList extends React.Component {
  constructor(props) {
    super(props);
    this.chatsList = React.createRef();
  }

  getSnapshotBeforeUpdate(prevProps, prevState) {
    if (prevProps.list.length < this.props.list.length) {
      const list = this.chatsList.current;
      return list.scrollHeight - list.scrollTop;
    }
    return null;
  }

  componentDidUpdate(prevProps, prevState, snapshot) {
     if (snapshot !== null) {
      const list = this.chatsList.current;
      list.scrollTop = list.scrollHeight - snapshot;
    }
  }

  render() {
    return (
      <div ref={this.chatsList}>{/* ...contents... */}</div>
    );
  }
}


The componentDidUpdate Method  componentDidUpdate 方法
The componentDidUpdate method is the last lifecycle method invoked in the update phase. It allows you to create side effects like sending network requests or calling the this.setState method. It’s important to remember that there should always be a way to avoid the setState (like some sort of logic), or it will result in an infinite loop of re-rendering.
componentDidUpdate 方法是更新阶段调用的最后一个生命周期方法。它允许您创建副作用,例如发送网络请求或调用 this.setState 方法。重要的是要记住,应该始终有一种方法来避免 setState (就像某种逻辑),否则它会导致重新渲染的无限循环。

This method can accept up to three parameters: prevProps, prevState, and snapshot (if you implement the getSnapshotBeforeUpdate method).
此方法最多可以接受三个参数: prevProps 、 prevState 和 snapshot (如果您实现了 getSnapshotBeforeUpdate 方法)。

Here's an example of using componentDidUpdate method for implementing autosave functionality:
下面是使用 componentDidUpdate 方法实现自动保存功能的示例:


class WritePost extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            postContent: ""
        };

        this.handleInput = this.handleInput.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
    }

    handleInput(e) {
        this.setState({postContent: this.state.postContent + e.target.value})
    }

    handleSubmit() {
        // ...
    }

    autosave() {
        // send network request to save post...
    }

    componentDidUpdate() {
        this.autosave()
    }

    render() {
        return(
            <form onSubmit={this.handleSubmit}>
                <input type={text} value={this.state.postContent} onChange={e => handleInput(e)} />
                <button type="submit">Post</button>
            </form>
        )
    }
}

The unmounting phase 卸载阶段
The unmounting phase is the third and final phase of a React component. At this phase, the component is removed from the DOM. Unmounting only has one lifecycle method involved: componentWillUnmount.
卸载阶段是 React 组件的第三个也是最后一个阶段。在此阶段,组件将从 DOM 中移除。卸载只涉及一种生命周期方法: componentWillUnmount 。

The componentWillUnmount Method  componentWillUnmount 方法
componentWillUnmount is invoked right before the component is unmounted or removed from the DOM. It’s meant for any necessary clean up of the component, like unsubscribing to any subscriptions (i.e., Redux) or canceling any network requests. Once this method is done executing, the component will be destroyed.
componentWillUnmount 在组件被卸载或从 DOM 中移除之前被调用。它用于对组件进行任何必要的清理,例如取消订阅任何订阅(即 Redux)或取消任何网络请求。一旦此方法执行完毕,组件将被销毁。

Here's an example of using the componentWillUnmount to unsubscribe from a Redux store:
下面是使用 componentWillUnmount 取消订阅 Redux 商店的示例:


class MyComponent extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            ...
        }

        // whatever bindings...
    }

    componentDidMount() {
        const { subscribe } = this.props.store;
        this.unsubscribe = subscribe(this.forceUpdate);
    }

    componentWillUnmount() {
        this.unsubscribe();
    }

    render() {
        return (
            <div>
                ...
            </div>
        )
    }
}

React Hooks and the component lifecycle
React Hooks 和组件生命周期
Versions of React before 16.8 consider two kinds of components based on statefulness: the class-based stateful component, and the stateless functional components (often referred to as a “dumb component”). But with the release of React 16.8, Hooks were introduced and empowered developers to access state from functional components, instead of writing an entire class. With this change, building components became easier and less verbose.
React 16.8 之前的版本考虑了两种基于状态的组件:基于类的有状态组件和无状态功能组件(通常称为“哑组件”)。但随着 React 16.8 的发布,引入了 Hooks 并使开发人员能够从功能组件访问状态,而不是编写整个类。通过此更改,构建组件变得更加容易且不那么冗长。

Hooks known as default hooks come with React, and you’re also able to create your own custom hook. A custom hook is just a function that starts with use, like useStore, or useWhatever.
被称为默认钩子的钩子是 React 自带的,你也可以创建自己的自定义钩子。自定义钩子只是一个以 use 开头的函数,例如 useStore 或 useWhatever 。

The two most common default hooks are useState and useEffect. The useState hook gives state to the functional component, and useEffect allows you to add side effects within it (like after initial render), which aren’t allowed within the function's main body. You can also act upon updates on the state with useEffect.
两个最常见的默认钩子是 useState 和 useEffect 。 useState 钩子为功能组件提供状态, useEffect 允许您在其中添加副作用(比如在初始渲染之后),这在函数的主体中是不允许的。您还可以使用 useEffect 根据状态更新采取行动。

React has released more default hooks, but useState and useEffect are the ones you should be most familiar with. Let’s take a look at how they work and compare them to the component lifecycle we covered above.
React 发布了更多的默认钩子,但是 useState 和 useEffect 是你应该最熟悉的。让我们看看它们是如何工作的,并将它们与我们上面介绍的组件生命周期进行比较。

useState
The useState hook is used to store state for a functional component. This hook accepts one parameter: initialState, which will be set as the initial stateful value, and returns two values: the stateful value, and the update function to update the stateful value. The update function accepts one argument, newState, which replaces the existing stateful value.
useState 钩子用于存储功能组件的状态。这个钩子接受一个参数: initialState ,它会被设置为初始有状态值,并返回两个值:有状态值和更新有状态值的更新函数。 update 函数接受一个参数 newState ,它替换现有的有状态值。

Let's say you have this class-based component:
假设您有这个基于类的组件:


class MyInput extends React.Component {
  constructor(props) {
    super(props);
    this.state = { input: "" };

    this.handleChange = this.handleChange.bind(this);
  }

  handleChange(e) {
    this.setState({ input: e.target.value });
  }

  render() {
    return (
      <input
        type="text"
        value={this.state.input}
        onChange={this.handleChange}
      />
    );
  }
}

Converting this to a functional component with useState eliminates a lot of code and makes things cleaner and shorter. Here's what the above component looks like with the useState hook. If you’ve read a React tutorial over the past 2 years, chances are you’ve seen some syntax like this.
使用 useState 将其转换为功能组件可消除大量代码并使内容更简洁。这是带有 useState 挂钩的上述组件的样子。如果你在过去 2 年里阅读过 React 教程,你很可能见过这样的语法。

import { useState } from 'react';


function MyInput(props) {
    const [input, setInput] = useState('');

    return (
        <input
            value={input}
            onChange={e => setInput(e.target.value)}
        />
    )
}

With useState(), whatever you put in the parenthesis is the default state.
对于 useState() ,括号中的任何内容都是默认状态。

The simplicity and clarity of these functional components with Hooks popularized their use among developers who prefer using functional components rather than traditional, class-based ones.
这些带有 Hooks 的功能组件的简单性和清晰性在喜欢使用功能组件而不是传统的基于类的组件的开发人员中普及了它们的使用。

But what if your class-based component’s state object has plenty of items like this:
但是,如果基于类的组件的状态对象有很多这样的项目怎么办:


class MyComponent extends React.Component {
  constructor(props) {
    super(props);

    // this component has multiple items in the state object
    this.state = {
      count: 0,
      counterWeight: 1,
      themeMode: "light"
    };

    // ...
  }

  // ...

  render() {
    return (
      <div class={this.state.themeMode}>
          ...
      </div>
    );
  }
}

You might be tempted at first to use one useState hook, and build some sort of dictionary to hold all of this state. But React allows you to have multiple useState hooks within a functional component. So instead of one single object, you can set each item of the state object into its own state:
一开始您可能想使用一个 useState 挂钩,并构建某种字典来保存所有这些状态。但是 React 允许你在一个功能组件中有多个 useState 钩子。因此,您可以将状态对象的每一项设置为它自己的状态,而不是一个单独的对象:


function MyComponent(props) {
    const [count, setCount] = useState(0);
    const [counterWeight, setCounterWeight] = useState(1);
    const [themeMode, setThemeMode] = useState('light');

    // the rest of the code...

    return (
        <div>
            ...
        </div>
    )
}

With a lot of different “types” of state this can obviously get verbose, so exercise judgment for larger components.
对于许多不同“类型”的状态,这显然会变得冗长,因此请对较大的组件进行判断。

useEffect
As with the render() method of a class-based component, the main body of a functional component should be kept pure. With the useEffect hook, you're able to create side effects while maintaining the component's purity. Within this hook, you can send network requests, make subscriptions, and change the state value.
与基于类的组件的 render() 方法一样,功能组件的主体应该保持纯净。使用 useEffect 钩子,您可以在保持组件纯度的同时创建副作用。在此挂钩中,您可以发送网络请求、进行订阅和更改 state 值。

The useEffect hook accepts a function as an argument, where you write all your side effects. This function is invoked after every browser paint and before any new renders (this will depend on the dependency array, which is explained in the next paragraph). This function can return another function called the clean-up function, which can be used to clean up the side effects (i.e. when the component is destroyed) like unsubscribing to a store. It’s kind of a mash up of several of the methods explained in the previous section.
useEffect 钩子接受一个函数作为参数,您可以在其中编写所有的副作用。这个函数在每次浏览器绘制之后和任何新渲染之前被调用(这将取决于依赖数组,这将在下一段中解释)。此函数可以返回另一个称为清理函数的函数,该函数可用于清理副作用(即当组件被销毁时),如取消订阅商店。它是上一节中介绍的几种方法的混合体。

This Hook accepts a second argument called the dependency array, which is an array of dependencies like state or props values, which the useEffect uses as reference to only run when these values change. If the dependency array is empty, then the useEffect will only run once, after the first paint.
此 Hook 接受称为依赖项数组的第二个参数,它是一个依赖项数组,如 state 或 props 值, useEffect 将其用作仅在这些值更改时运行的参考。如果依赖数组为空,那么 useEffect 将只运行一次,在第一次绘制之后。

The dependency array is optional, so if it's not defined, useEffect will fire first when the component is first mounted, and then on every re-render.
依赖项数组是可选的,因此如果未定义, useEffect 将在首次安装组件时首先触发,然后在每次重新渲染时触发。

Here's an example of a functional component using useEffect that subscribes to a Redux store:
下面是一个使用 useEffect 订阅 Redux 存储的功能组件示例:

import { useEffect } from 'react';


function MyComponent(props) {
    // ...

    useEffect(() => {
        const { subscribe } = props.store;
        const unsubscribe = subscribe(...);
        return unsubscribe
    }, []);

    return 
}

This component's useEffect will only run once, since the dependency array is empty. Within the input function, the subscription to the Redux store is invoked, which returns an unsubscribe function. This unsubscribe function is returned, which serves as the clean-up function.
该组件的 useEffect 将只运行一次,因为依赖项数组是空的。在输入函数中,调用对 Redux 存储的订阅,它返回一个 unsubscribe 函数。返回这个 unsubscribe 函数,作为清理函数。

You might have noticed that the useEffect from the above component has similarities to componentDidMount. It holds the side effects, and only runs once, when the component is mounted. The only difference is that it's invoked after the first browser paint, whereas componentDidMount doesn’t wait for that. It’s also important to note that the clean-up function can be compared to the componentWillUnmount, as this function is invoked when the component was destroyed. So again, useEffect() is a sort of hybrid in this sense.
您可能已经注意到,上述组件中的 useEffect 与 componentDidMount 有相似之处。它具有副作用,并且只在安装组件时运行一次。唯一的区别是它是在第一次浏览器绘制之后调用的,而 componentDidMount 不会等待它。同样重要的是要注意,清理函数可以与 componentWillUnmount 进行比较,因为当组件被销毁时会调用此函数。因此,从这个意义上说, useEffect() 是一种混合体。

The useEffect hook works similarly to the three lifecycle methods: componentDidMount, componentDidUpdate, and componentWillUnmount. The componentDidMount and componentWillUnmount were discussed above, but what about componentDidUpdate?
useEffect 钩子的工作方式类似于三个生命周期方法: componentDidMount 、 componentDidUpdate 和 componentWillUnmount 。上面讨论了 componentDidMount 和 componentWillUnmount ,但是 componentDidUpdate 呢?

If you add dependencies in the dependency array, the function passed into the useEffect hook will run every time the dependencies, like a piece of stateful data, changes. This behavior of the useEffect hook is comparable to the componentDidUpdate method since it’s invoked on every state/props change. The difference is that you can specifically choose what state/props you want useEffect to depend on, rather than the componentDidUpdate which acts upon every state or props change.
如果您在依赖项数组中添加依赖项,传入 useEffect 挂钩的函数将在每次依赖项(如有状态数据)发生更改时运行。 useEffect 钩子的这种行为与 componentDidUpdate 方法相当,因为它在每次状态/道具更改时都会被调用。不同之处在于,您可以专门选择您希望 useEffect 依赖的状态/道具,而不是作用于每个 state 或 props 更改的 componentDidUpdate 。

Conclusion 结论
In React, a component can enter three different phases that make up its lifecycle. These phases are mounting, updating, and unmounting. Each phase has lifecycle methods invoked, where you can work on different things related to the component, like its props and state, or actually mounting the component to the DOM (with the render method). However, these methods are only for class-based components.
在 React 中,组件可以进入构成其生命周期的三个不同阶段。这些阶段是挂载、更新和卸载。每个阶段都会调用生命周期方法,您可以在其中处理与组件相关的不同事情,例如它的 props 和 state ,或者实际将组件安装到 DOM(使用 render 方法)。但是,这些方法仅适用于基于类的组件。

With the release of React 16.8, developers can now write stateful functional components with Hooks, which eliminates a lot of verbosity in a class-based component, and makes the code easier and simpler to write and read. The two most commonly used default hooks are useState and useEffect which are used to handle stateful data in a functional component and for creating side effects within. useEffect works similarly to the three lifecycle methods: componentDidMount, componentDidUpdate, and componentWillUnmount.
随着 React 16.8 的发布,开发人员现在可以使用 Hooks 编写有状态的功能组件,这消除了基于类的组件中的大量冗长,并使代码更容易编写和阅读。两个最常用的默认钩子是 useState 和 useEffect ,它们用于处理功能组件中的有状态数据以及在其中创建副作用。 useEffect 的工作方式类似于三种生命周期方法: componentDidMount 、 componentDidUpdate 和 componentWillUnmount 。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

光剑书架上的书

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值