简体   繁体   中英

React: SetInterval in ComponentDidMount causing error "Warning: Can't perform a React state update on an unmounted component."

I want to add a typing effect to a component in my React app and I'm using setInterval to do this. Everything works fine but I'm getting the following error:

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

The function starts in componentDidMount() so I don't understand why it's saying that I'm updating an unmounted component. I've tried to add clearInterval() in componentWillUnmount() but the error still shows.

Code:

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> 
}

I think the problem with your code is that you are saving intervalId in the state of the component.
As you probably know when you call setState it causes rerender .
you can save your intervalId in the attribute of class.
please consider these changes in your code:

  1. Define an attribute in your class like this
    class MyClsss extends React.component{ intervalId = ""; ... }
  2. Save your interval id in this attribute like this
     this.intervalId = setInterval(...)
  3. Clear your interval wherever you want this way
    clearInterval(this.intervalId);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM