反应:ComponentDidMount中的SetInterval导致错误“警告:无法对已卸载的组件执行反应状态更新。”

时间:2020-03-15 07:55:18

标签: javascript reactjs asynchronous setinterval

我想在我的React应用程序的组件中添加打字效果,而我正在使用setInterval来做到这一点。一切正常,但出现以下错误:

Warning: Can't perform a React state update on an unmounted component. 
This is a no-op, but it indicates a memory leak in your application. 
To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method

该函数始于componentDidMount(),所以我不明白为什么要更新卸载的组件。我尝试在clearInterval()中添加componentWillUnmount(),但错误仍然显示。

代码:

componentDidMount = () => {
    this.typeText();
}

componentWillUnmount(){
    console.log(this.state.intervalId);
    clearInterval(this.state.intervalId);
}

typeText = () => {
    const sp = (text,key) => <span key={key} style={{whiteSpace: 'pre-line'}}>{text}</span>;
    const results = this.state.screenText;
    let start = 0;
    let cursor = 0;
    const intervalId = setInterval(() => {
        if (results.length) results.pop();
        const str = this.state.text.slice(start,cursor);
        const span = sp(str,cursor);
        results.push(span);
        this.setState({screenText:results});
        start = Math.floor((cursor / 80));
        cursor += 1;
        if (cursor > this.state.text.length) clearInterval(intervalId);  
    },5);

    this.setState({intervalId: intervalId});       
    console.log(this.state.intervalId);  
}
render() {
    return <span id="typing"> {this.state.screenText}</span> 
}

1 个答案:

答案 0 :(得分:2)

我认为您的代码存在问题,就是您正在将intervalId保存为组件状态。
您可能知道,当您致电setState时,它会导致rerender
您可以将intervalId保存在class属性中。
请考虑代码中的以下更改:

  1. 像这样在类中定义属性
    class MyClsss extends React.component{
      intervalId = "";
        ...
    }
    
  2. 像这样在此属性中保存间隔ID
    this.intervalId = setInterval(...)
    
  3. 以这种方式清除间隔
    clearInterval(this.intervalId);