React 生命周期函数详解

React 组件在其生命周期中有多个阶段,每个阶段都有特定的生命周期函数(Lifecycle Methods)。这些函数允许你在组件的不同阶段执行特定的操作。以下是 React 组件生命周期的主要阶段及其对应的生命周期函数,并结合了 React 16.3+ 的变化。


一、挂载阶段(Mounting)

在组件首次被挂载到 DOM 时会触发的一系列生命周期函数。

  • constructor(props)

    • 初始化组件的状态和绑定事件处理器。
    • 注意:尽量避免在此进行复杂的计算或副作用操作。
    js 复制代码
    constructor(props) {
      super(props);
      this.state = { count: 0 };
      this.handleClick = this.handleClick.bind(this); // 绑定事件处理器
    }
  • static getDerivedStateFromProps(nextProps, prevState)

    • 在组件挂载和更新之前调用,用于根据新的 props 更新 state。
    • 返回一个对象来更新 state,或者返回 null 表示不需要更新。
    js 复制代码
    static getDerivedStateFromProps(nextProps, prevState) {
      if (nextProps.value !== prevState.value) {
        return { value: nextProps.value };
      }
      return null;
    }
  • render()

    • 必须实现的方法,用于渲染组件的虚拟 DOM。
    • 不应该在这里进行副作用操作(如 API 调用、DOM 操作等)。
    js 复制代码
    render() {
      return <div>{this.state.count}</div>;
    }
  • componentDidMount()

    • 组件挂载完成后调用,通常用于发起网络请求、订阅事件等副作用操作。
    js 复制代码
    componentDidMount() {
      fetch('/api/data').then(response => this.setState({ data: response.data }));
    }

二、更新阶段(Updating)

当组件的 props 或 state 发生变化时,会触发一系列更新阶段的生命周期函数。

  • static getDerivedStateFromProps(nextProps, prevState)

    • 同挂载阶段的 getDerivedStateFromProps,用于根据新的 props 更新 state。
  • shouldComponentUpdate(nextProps, nextState)

    • 判断组件是否需要重新渲染。返回 false 可以阻止不必要的重新渲染,从而优化性能。
    js 复制代码
    shouldComponentUpdate(nextProps, nextState) {
      return nextState.count !== this.state.count;
    }
  • render()

    • 同挂载阶段的 render() 方法,用于渲染组件的虚拟 DOM。
  • getSnapshotBeforeUpdate(prevProps, prevState)

    • 在最新的渲染输出提交给 DOM 之前调用,可以捕获一些 DOM 信息(如滚动位置),以便在 componentDidUpdate 中使用。
    js 复制代码
    getSnapshotBeforeUpdate(prevProps, prevState) {
      if (prevProps.items.length < this.props.items.length) {
        return this.listRef.scrollHeight;
      }
      return null;
    }
  • componentDidUpdate(prevProps, prevState, snapshot)

    • 组件更新完成后调用,可以在此进行副作用操作(如网络请求、DOM 操作等)。
    js 复制代码
    componentDidUpdate(prevProps, prevState, snapshot) {
      if (snapshot !== null) {
        this.listRef.scrollTop = this.listRef.scrollHeight - snapshot;
      }
    }

三、卸载阶段(Unmounting)

当组件从 DOM 中卸载时会触发的生命周期函数。

  • componentWillUnmount()

    • 组件卸载和销毁之前立刻调用,通常用于清理工作,如取消网络请求、清除定时器、移除事件监听器等。
    js 复制代码
    componentWillUnmount() {
      clearInterval(this.timerID);
      this.subscription.remove();
    }

四、错误处理阶段(Error Handling)

当组件抛出错误时会触发的生命周期函数。

  • static getDerivedStateFromError(error)

    • 当子组件抛出错误时调用,用于更新 state 以便显示错误 UI。
    js 复制代码
    static getDerivedStateFromError(error) {
      return { hasError: true };
    }
  • componentDidCatch(error, info)

    • 当子组件抛出错误时调用,通常用于记录错误日志或上报错误。
    js 复制代码
    componentDidCatch(error, info) {
      logErrorToService(error, info);
    }

五、React 16.3+ 生命周期变化

随着 React 16.3+ 的发布,部分生命周期函数被废弃或新增了一些新的生命周期函数:

  • 废弃的生命周期

    • componentWillMount(建议使用 componentDidMount
    • componentWillReceiveProps(建议使用 static getDerivedStateFromProps
    • componentWillUpdate(建议使用 getSnapshotBeforeUpdate
  • 新增的生命周期

    • getDerivedStateFromProps:用于在挂载和更新前根据 props 更新 state。
    • getSnapshotBeforeUpdate:在最新的渲染输出提交给 DOM 之前调用,捕获一些 DOM 信息。

钩子函数(Hooks)

随着 React Hooks 的引入,许多类组件的生命周期方法可以通过钩子函数来实现:

  • useEffect

    • 相当于 componentDidMountcomponentDidUpdatecomponentWillUnmount 的组合。
    js 复制代码
    useEffect(() => {
      // 类似 componentDidMount 和 componentDidUpdate
      fetchData().then(data => setState({ data }));
    
      // 清理函数,类似 componentWillUnmount
      return () => {
        cleanup();
      };
    }, [props.userID]); // 依赖项数组
  • useLayoutEffect

    • 类似 useEffect,但在所有 DOM 变更之后同步调用,适用于需要同步执行的副作用操作。
  • useMemouseCallback

    • 用于性能优化,类似于 shouldComponentUpdate

总结

React 组件的生命周期分为三个主要阶段:挂载(Mounting)、更新(Updating)和卸载(Unmounting)。每个阶段都有相应的生命周期函数,帮助开发者在组件的不同生命周期中执行特定的操作。

  • 挂载阶段:初始化状态、渲染组件、发起数据请求等。
  • 更新阶段:判断是否需要重新渲染、捕获 DOM 信息、执行副作用操作等。
  • 卸载阶段:清理资源、取消订阅等。

通过合理使用这些生命周期函数,可以构建出更加健壮和高效的 React 应用程序。同时,现代 React 开发中推荐使用 Hooks 来替代类组件的生命周期方法,以简化代码并提高可维护性。

理解这些生命周期函数及其作用,不仅有助于编写高效且易于维护的 React 组件,还能更好地应对复杂的应用场景。

相关推荐
龙井>_<13 分钟前
vue3+Ts+elementPlus二次封装Table分页表格,表格内展示图片、switch开关、支持
前端·javascript·vue.js·elementplus
冴羽13 分钟前
SvelteKit 最新中文文档教程(5)—— 页面选项
前端·javascript·svelte
*goliter *14 分钟前
html重点知识总结
前端·html
无名之逆24 分钟前
探索Hyperlane:用Rust打造轻量级、高性能的Web后端框架
服务器·开发语言·前端·后端·算法·rust
努力的搬砖人.32 分钟前
JavaScript相关面试题
javascript
狂炫一碗大米饭1 小时前
🧠前端面试高频考题---promise,从五个方面搞定它🛠️
前端·javascript·面试
拉不动的猪2 小时前
前端如何判断登录设备是移动端还是pc端
前端·javascript·css
小圆脸儿2 小时前
通用组件库设计方案ui-components
前端·前端框架
拉不动的猪2 小时前
刷刷题38(长连接 +切片上传)
前端·javascript·面试