React 所有的生命周期函数,以及用法

156 阅读5分钟

React 组件的生命周期是指从组件的创建、更新到销毁的整个过程。React 16 及之前的版本,组件的生命周期方法主要分为三类:挂载(Mounting)、更新(Updating)和卸载(Unmounting)。React 18 引入了新的并发模式(Concurrent Mode),并推荐使用新的生命周期钩子函数 getSnapshotBeforeUpdategetDerivedStateFromProps 来替代一些旧的用法,同时一些老的生命周期方法可能会在未来的版本中被弃用。以下是 React 生命周期的详细总结及其用法:

挂载(Mounting)

  1. constructor(props)

    • 在创建组件实例时调用。
    • 初始化 state 或绑定方法。
    constructor(props) {
      super(props);
      this.state = { count: 0 };
    }
    
  2. static getDerivedStateFromProps(props, state)

    • 在渲染之前调用,用于根据 props 更新 state。
    • 返回一个对象以更新 state,或者返回 null 表示不需要更新。
    static getDerivedStateFromProps(props, state) {
      if (props.newValue !== state.value) {
        return { value: props.newValue };
      }
      return null;
    }
    
  3. render()

    • 必需的,返回 React 元素,用于描述 UI。
    render() {
      return <div>{this.state.count}</div>;
    }
    
  4. componentDidMount()

    • 在组件挂载后立即调用,适用于引入任何需要从 DOM 节点操作的功能,如网络请求或订阅。
    componentDidMount() {
      this.fetchData();
    }
    

更新(Updating)

  1. static getDerivedStateFromProps(props, state)

    • 在接收到新的 props 或 state 之前调用,用于根据新 props 更新 state。
  2. shouldComponentUpdate(nextProps, nextState)

    • 在渲染之前调用,返回 true 或 false 来决定是否重新渲染组件。
    • 用于性能优化。
    shouldComponentUpdate(nextProps, nextState) {
      return nextProps.count !== this.props.count;
    }
    
  3. render()

    • 同上。
  4. getSnapshotBeforeUpdate(prevProps, prevState)

    • 在最近一次渲染输出(提交到 DOM 节点)之前调用。
    • 返回一个值作为 componentDidUpdate 的第三个参数。
    getSnapshotBeforeUpdate(prevProps, prevState) {
      if (prevProps.list.length < this.props.list.length) {
        const listItem = document.querySelector('.item');
        return listItem.scrollHeight;
      }
      return null;
    }
    
  5. componentDidUpdate(prevProps, prevState, snapshot)

    • 在更新后立即调用,适用于当组件更新后需要执行的操作。
    • 如 DOM 操作或更新网络请求。
    componentDidUpdate(prevProps, prevState, snapshot) {
      if (prevProps.list.length < this.props.list.length) {
        this.scrollToBottom(snapshot);
      }
    }
    

卸载(Unmounting)

  1. componentWillUnmount()
    • 在组件卸载及销毁之前调用。
    • 适用于清除 timer、取消网络请求或清除订阅。
    componentWillUnmount() {
      clearInterval(this.timer);
    }
    

错误处理(Error Handling)

  1. static getDerivedStateFromError(error)

    • 在渲染期间、生命周期方法和构造函数中抛出错误之后调用。
    • 允许组件捕获错误并渲染备用 UI。
    static getDerivedStateFromError(error) {
      return { hasError: true };
    }
    
  2. componentDidCatch(error, errorInfo)

    • 在捕获到后代组件中的 JavaScript 错误时调用。
    • 适用于记录错误信息到服务器。
    componentDidCatch(error, errorInfo) {
      logErrorToServer(error, errorInfo);
    }
    

注意事项

  • React Hooks:React 16.8 引入了 Hooks,它们提供了一种更函数式的方式来使用 state 和其他 React 特性,而不必依赖于类组件的生命周期方法。
  • 未来变化React 生命周期函数(续)

关于React Hooks与类组件生命周期的对比

React Hooks的引入为函数式组件提供了使用state和其他React特性的能力,从而减少了对类组件及其生命周期方法的依赖。然而,对于仍然使用类组件的开发者来说,理解生命周期方法仍然至关重要。

生命周期方法的常见使用场景

  1. constructor

    • 初始化state和绑定事件处理函数。
    • 注意:在React 16.3及更高版本中,可以在类字段中直接声明state,从而避免在constructor中初始化state。
  2. componentDidMount

    • 发送网络请求以获取数据。
    • 订阅外部数据源(如WebSocket)。
    • 在DOM上执行测量或手动设置焦点。
  3. shouldComponentUpdate

    • 性能优化:通过比较新旧props和state来决定是否重新渲染组件。
    • 注意:在React的并发模式下,shouldComponentUpdate的行为可能会有所不同,因为它不再保证同步更新。
  4. componentDidUpdate

    • 更新后的DOM操作,如滚动到页面底部。
    • 在更新后重新执行网络请求(如分页加载)。
  5. componentWillUnmount

    • 清除定时器、取消网络请求或移除事件监听器。
    • 清理组件在componentDidMount中设置的任何外部资源。

生命周期方法的注意事项

  • 避免在生命周期方法中进行复杂的计算或副作用:这些操作应该放在useEffect(对于函数组件)或componentDidMount/componentDidUpdate(对于类组件)等适当的生命周期方法中,并确保在componentWillUnmount中进行清理。
  • 理解生命周期方法的调用顺序:这对于调试和避免潜在的bug至关重要。例如,在componentDidMount中设置的状态更新将触发后续的shouldComponentUpdate和componentDidUpdate方法。
  • 注意React版本差异:随着React版本的更新,一些生命周期方法可能会被弃用或替换为新的API。因此,建议查阅最新的React文档以获取最准确的信息。

替代方案与未来趋势

  • React Hooks:作为类组件生命周期方法的替代方案,Hooks提供了一种更灵活、更函数式的方式来处理state、副作用和生命周期。它们允许你在函数组件中使用state和其他React特性,而无需转换为类组件。
  • 并发模式(Concurrent Mode):React的并发模式旨在提高应用的响应性和性能。它引入了一些新的API和概念,如Suspense和lazy loading,以及可能改变现有生命周期方法行为的并发更新。因此,建议开发者关注React的并发模式发展,并考虑在未来的项目中采用这些新特性。

虽然React的生命周期方法在类组件中仍然扮演着重要角色,但随着React Hooks和并发模式的引入,开发者有了更多选择来构建高效、可维护的React应用。