MST
星途 面试题库

面试题:React 中 componentWillUnmount 的触发场景及常见清理操作

请描述在 React 应用中,componentWillUnmount 方法会在哪些场景下被触发?并列举至少三种在该方法中通常需要进行的清理操作。
42.2万 热度难度
前端开发React

知识考点

AI 面试

面试题答案

一键面试

componentWillUnmount 方法触发场景

  1. 组件被卸载时:例如,当通过条件渲染控制组件显示与隐藏,条件变化使得组件从页面中移除时触发。比如在一个模态框组件中,当关闭按钮被点击,控制模态框显示的状态发生变化,模态框组件将被卸载,此时会触发 componentWillUnmount
  2. 路由切换导致组件卸载:在单页应用(SPA)中,使用 React Router 等路由库时,当路由发生变化,原路由对应的组件会被卸载,componentWillUnmount 会被调用。例如从 /home 页面切换到 /about 页面,Home 组件会被卸载。
  3. 父组件重新渲染导致子组件卸载:如果父组件由于状态变化或属性变化而重新渲染,并且子组件不再满足渲染条件,子组件会被卸载,从而触发 componentWillUnmount。例如父组件根据某个条件决定是否渲染某个子组件,当条件变化使得子组件不再被渲染时。

通常进行的清理操作

  1. 清除定时器:如果组件中使用了 setIntervalsetTimeout 创建定时器,在组件卸载时需要清除,防止内存泄漏。例如:
class MyComponent extends React.Component {
    constructor(props) {
        super(props);
        this.timer = null;
    }
    componentDidMount() {
        this.timer = setInterval(() => {
            console.log('定时器运行中');
        }, 1000);
    }
    componentWillUnmount() {
        clearInterval(this.timer);
    }
    render() {
        return <div>组件内容</div>;
    }
}
  1. 取消网络请求:如果组件发起了网络请求,在组件卸载时,若请求还未完成,需要取消请求,避免响应回来后操作已不存在的组件,导致错误。例如使用 axios 库时:
import React, { Component } from'react';
import axios from 'axios';

class MyComponent extends Component {
    constructor(props) {
        super(props);
        this.source = axios.CancelToken.source();
    }
    componentDidMount() {
        axios.get('/api/data', {
            cancelToken: this.source.token
        }).then(response => {
            console.log(response.data);
        }).catch(error => {
            if (!axios.isCancel(error)) {
                console.error(error);
            }
        });
    }
    componentWillUnmount() {
        this.source.cancel('组件已卸载,取消请求');
    }
    render() {
        return <div>组件内容</div>;
    }
}
  1. 解绑事件监听器:如果在 componentDidMount 中给 DOM 元素添加了事件监听器,在组件卸载时要解绑,防止内存泄漏。例如:
class MyComponent extends React.Component {
    handleClick = () => {
        console.log('按钮被点击');
    }
    componentDidMount() {
        document.addEventListener('click', this.handleClick);
    }
    componentWillUnmount() {
        document.removeEventListener('click', this.handleClick);
    }
    render() {
        return <div>组件内容</div>;
    }
}