MST

星途 面试题库

面试题:React组件销毁时如何正确清理副作用

假设在一个React组件中,使用了定时器setInterval以及订阅了一些外部事件,在组件销毁阶段,如何确保这些副作用被正确清理,避免内存泄漏?请给出具体的代码示例说明。
21.5万 热度难度
前端开发React

知识考点

AI 面试

面试题答案

一键面试

在React组件中,可以通过useEffect钩子结合useRef钩子以及componentWillUnmount(在类组件中)来处理这种情况。以下是函数组件和类组件的示例:

函数组件

import React, { useEffect, useRef } from 'react';

const TimerComponent = () => {
    const intervalRef = useRef(null);
    const eventListenerRef = useRef(null);

    useEffect(() => {
        // 设置定时器
        intervalRef.current = setInterval(() => {
            console.log('定时器在运行');
        }, 1000);

        // 订阅外部事件
        const handleExternalEvent = () => {
            console.log('外部事件被触发');
        };
        window.addEventListener('resize', handleExternalEvent);
        eventListenerRef.current = handleExternalEvent;

        // 清理副作用
        return () => {
            if (intervalRef.current) {
                clearInterval(intervalRef.current);
            }
            if (eventListenerRef.current) {
                window.removeEventListener('resize', eventListenerRef.current);
            }
        };
    }, []);

    return <div>定时器和事件订阅示例组件</div>;
};

export default TimerComponent;

类组件

import React, { Component } from 'react';

class TimerClassComponent extends Component {
    constructor(props) {
        super(props);
        this.intervalRef = null;
        this.eventListenerRef = null;
    }

    componentDidMount() {
        // 设置定时器
        this.intervalRef = setInterval(() => {
            console.log('定时器在运行');
        }, 1000);

        // 订阅外部事件
        const handleExternalEvent = () => {
            console.log('外部事件被触发');
        };
        window.addEventListener('resize', handleExternalEvent);
        this.eventListenerRef = handleExternalEvent;
    }

    componentWillUnmount() {
        if (this.intervalRef) {
            clearInterval(this.intervalRef);
        }
        if (this.eventListenerRef) {
            window.removeEventListener('resize', this.eventListenerRef);
        }
    }

    render() {
        return <div>定时器和事件订阅示例类组件</div>;
    }
}

export default TimerClassComponent;

在函数组件中,useEffect返回的清理函数会在组件卸载时执行,用于清理定时器和移除事件监听器。在类组件中,componentWillUnmount方法在组件卸载时执行相同的清理操作,从而避免内存泄漏。