反应钩子setState,setTimeout内存泄漏

时间:2020-10-17 10:05:44

标签: reactjs memory-leaks react-hooks settimeout use-effect

import React, { useState, useEffect, useRef } from 'react';
import styles from './TextAnimation.module.scss';

const TextAnimation = () => {
    const [typedText, setTypedText] = useState([
        "Welcome to Byc",
        "Change your Life"
    ]);
    const [value, setValue] = useState();
    const [inType, setInType] = useState(false);
    
    
    
    let attachClasses = [styles.Blink];
    if(inType) {
        attachClasses.push(styles.Typing)
    }
        
    const typingDelay = 200;
    const erasingDelay = 100;
    const newTextDelay = 5000;
    
    let textArrayIndex = 0;
    let charIndex = 0;
    
    const type = () => {
        if(charIndex < typedText[textArrayIndex].length + 1) {
            setValue(typedText[textArrayIndex].substring(0, charIndex));
            charIndex ++;
            setTime();
        } else {
            setInType(false);
            setTimeout(erase, newTextDelay);
        }
    };
    
    const setTime = () => {
        setTimeout(type, typingDelay);
    };
    
    const erase = () => {
        if(charIndex > 0) {
            setValue(typedText[textArrayIndex].substring(0, charIndex - 1));
            charIndex --;
            setTimeout(erase, erasingDelay);
        } else {
            setInType(false);
            textArrayIndex ++;
            if(textArrayIndex >= typedText.length) {
                textArrayIndex = 0;
            }
            setTimeout(type, newTextDelay - 3100);
        }
    };

    useEffect(() => {
        type();
    }, [])
    
    
    return (
        <div className={styles.TextAnimation}>
            <span className={styles.Text} >{value}</span><span className={attachClasses.join(' ')} >&nbsp;</span>
        </div>
    );
};

export default TextAnimation;

我正在尝试制作文本动画,但我收到了一条像这样的消息...

警告:无法在已卸载的组件上执行React状态更新。这是空操作,但它表明应用程序中发生内存泄漏。要修复,请取消使用useEffect清理功能中的所有订阅和异步任务。

我该如何解决?

1 个答案:

答案 0 :(得分:0)

您需要在卸载组件时清除超时,否则可能会在卸载组件后运行超时。

要这样做:

  • 将每个超时的返回值存储在某个引用中的列表中(例如,以React.useRef为例)
  • useEffect中返回一个回调,以清除clearTimeout(<return value of setTimeout>)的超时