React: 组件的生命周期

20138
2022/11/16 01:52:44

本章将讨论 React 组件的常用生命周期。

为了描述直观,我们将先通过类式组件(这可能也是本教程最后一次使用类式组件了)来说明常用的生命周期,然后再通过函数式组件来描述 React 是如何使用 hooks 来让函数式组件拥有近乎生命周期方式的功能。

要明确一点:生命周期方法是由 React 自动调用的,而不是由程序员来手动调用。

常用生命周期

我希望你已经点开了上面说的完整的生命周期图标,并对照以下内容进行阅读。

日常开发中,常用的生命周期方法有:

  • render():渲染组件时调用。当 stateprops 发生改变时(当然还有诸如 forceUpdate()等,我们只讲常用的,不常用的不再赘述),会重新调用该方法,以实现组件的重绘。
  • componentDidMount():当组件完成挂载时调用。【应用场景:初始化数据,比如从后端API中获取数据、初始化定时器、初始化订阅等】
  • componentWillUnmount():当组件即将被卸载时调用。【应用场景:清理资源。比如清除定时器、取消订阅等】
import React from 'react';

class App extends React.Component {
  render() {
    console.log('render():渲染组件');
    return <h1>你好,axum.rs!</h1>;
  }
  componentDidMount() {
    console.log('componentDidMount():组件已挂载');
  }
  componentWillUnmount() {
    console.log('componentWillUnmount():组件即将被卸载');
  }
}

export default App;

本节代码:axum-rs-react-lifecycle

让函数式组件拥有“生命周期”

React 通过useEffect hook 让函数式组件拥有近乎生命周期方法的功能。该 hook 比较多形式,我们分别讨论。先看一下它的原型:

useEffect(回调函数[, 监听的 state]);

什么是“监听的 state”

监听的state 的值发生改变时,才会重新调用回调函数。如果没有设置该参数,则监听所有state,如果不想监听任何 state,请将该参数设置为空数组[]

模拟 componentDidMount()

回调函数的函数体,可以用来模拟 componentDidMount()

模拟 componentWillUnmount()

本节代码位于axum-rs-react-fn-lifecycle

案例:获取客户端IP

本案例将实现,使用 React 从 https://httpbin.org/ip 获取客户端IP。首先,我们直接使用浏览器打开这个网址,可看到返回以下内容:

{
  "origin": "具体的IP"
}

流程如下:

  • https://httpbin.org/ip 发起 GET 请求【componentDidMount()
  • 将请求的数据进行解析,并保存到组件的状态里【componentDidMount()
  • 使用 JSX 显示结果【render()

HTTP 请求依赖库

要发起 HTTP 请求,我们需要安装依赖,这里我们使用 axios

yarn add axios

使用类式组件实现

import axios from 'axios';
import React from 'react';

class App extends React.Component {
  state = {
    ip: '正在获取',
  };
  render() {
    return <h1>你好,你的IP是:{this.state.ip}</h1>;
  }
  componentDidMount() {
    axios
      .get('https://httpbin.org/ip')
      .then((resp) => resp.data)
      .then((data) => {
        this.setState({ ip: data.origin });
      })
      .catch((err) => {
        console.log(err);
      });
  }
}

export default App;

本节代码:axum-rs-react-lifecycle-get-ip

使用函数式组件实现

import axios from 'axios';
import React, { useEffect, useState } from 'react';

function App() {
  const [ip, setIp] = useState('正在获取');

  useEffect(() => {
    axios
      .get('https://httpbin.org/ip')
      .then((resp) => resp.data)
      .then((data) => {
        setIp(data.origin);
      })
      .catch((err) => {
        console.log(err);
      });
  }, []);
  return <h1>你好,你的IP是:{ip}</h1>;
}

export default App;

本节代码:axum-rs-react-fn-lifecycle-get-ip