React: SetInterval в ComponentDidMount, вызывающий ошибку «Предупреждение. Невозможно выполнить обновление состояния React для размонтированного компонента». - PullRequest
1 голос
/ 15 марта 2020

Я хочу добавить эффект ввода к компоненту в моем приложении 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 Ответ

2 голосов
/ 15 марта 2020

Я думаю, что проблема с вашим кодом в том, что вы сохраняете intervalId в состоянии компонента.
Как вы, вероятно, знаете, когда вы вызываете setState, это вызывает rerender.
, который вы можете сохранить ваш intervalId в атрибуте класса.
пожалуйста, учтите следующие изменения в вашем коде:

  1. Определите атрибут в вашем классе следующим образом
    class MyClsss extends React.component{
      intervalId = "";
        ...
    }
    
  2. Сохраните интервал идентификатор в этом атрибуте, как этот
    this.intervalId = setInterval(...)
    
  3. Очистите ваш интервал, где вы хотите таким образом
    clearInterval(this.intervalId);
    
...