MST
星途 面试题库

面试题:React 16+ 生命周期变迁下 componentWillUnmount 的替代与兼容

在 React 16 及后续版本中,生命周期发生了一些变化,部分旧的生命周期方法(如 componentWillUnmount 等)被标记为不安全使用。请详细阐述为什么这些方法被标记为不安全?如果项目要兼容旧版本 React 同时适配新版本,在处理 componentWillUnmount 相关逻辑时,你会采取哪些策略?
32.8万 热度难度
前端开发React

知识考点

AI 面试

面试题答案

一键面试

为什么部分旧生命周期方法被标记为不安全

  1. 异步渲染机制:React 16 引入了 Fiber 架构,支持异步渲染。在异步渲染过程中,组件可能会多次重复渲染,旧的 componentWill* 方法可能会在这个过程中被多次调用。例如 componentWillMount 在 React 16 之前只调用一次,但在异步渲染下可能被多次调用,这会导致一些副作用逻辑(如网络请求、订阅事件等)重复执行,造成数据不一致或其他意外情况。
  2. 打断渲染问题:Fiber 架构下,渲染过程可能会被打断,以便浏览器可以处理其他任务。旧的 componentWill* 方法没有考虑到这种打断机制,在打断过程中调用这些方法可能导致不一致的状态变化,而新的生命周期方法(如 getDerivedStateFromPropsgetSnapshotBeforeUpdate)设计为可以在这种复杂的渲染环境下安全使用。

兼容旧版本 React 同时适配新版本,处理 componentWillUnmount 相关逻辑的策略

  1. 使用 UNSAFE_componentWillUnmount:在新版本 React 中,虽然 componentWillUnmount 被标记为不安全,但仍然可以使用 UNSAFE_componentWillUnmount 来实现相同的功能。这种方式可以在新旧版本 React 中都正常工作,但在未来版本 React 中可能会被完全移除,所以只适用于临时过渡。例如:
class MyComponent extends React.Component {
  UNSAFE_componentWillUnmount() {
    // 清理定时器
    clearInterval(this.timer);
    // 取消网络请求
    this.abortController.abort();
  }
}
  1. 采用新的生命周期模式:在 React 16.3 及以上版本,推荐使用 useEffect Hook(对于函数组件)或 componentDidMountcomponentWillUnmount 的组合(对于类组件)来处理副作用和清理逻辑。
    • 函数组件
import React, { useEffect } from'react';

const MyFunctionComponent = () => {
  useEffect(() => {
    const timer = setInterval(() => {
      console.log('Interval running');
    }, 1000);
    return () => {
      clearInterval(timer);
    };
  }, []);

  return <div>My Function Component</div>;
};
  • 类组件
class MyClassComponent extends React.Component {
  componentDidMount() {
    this.timer = setInterval(() => {
      console.log('Interval running');
    }, 1000);
  }

  componentWillUnmount() {
    clearInterval(this.timer);
  }

  render() {
    return <div>My Class Component</div>;
  }
}
  1. 条件编译:可以使用工具如 Babel 插件,根据 React 版本进行条件编译。例如,在构建过程中,根据 React 版本判断,对于旧版本 React 使用 componentWillUnmount,对于新版本 React 使用 UNSAFE_componentWillUnmount 或新的生命周期模式。这种方式需要更复杂的配置,但可以实现更精细的控制。