How to clearTimeout an async function when componentWillUnmount in a Reactjs component?

10,573

Solution 1

Set a flag in your class inside componentWillUnmount.

In your async callback, check whether that flag has been set, and, if so, stop immediately.

Solution 2

You can certainly set a flag as suggested by @SLaks. This is similar to the isMounted pattern. ** note I changed to componentdidmount which is a better pattern I think **

class ChartComp extends Component{
    constructor(props){
        super(props);
        this.timer = null;
        this.loadData = this.loadData.bind(this);
    }

    componentDidMount() {
      this._mounted = true;
      this.loadData();
    }

    componentWillUnmount(){
        this._mounted = false;
        if(this.timer){
            clearTimeout(this.timer);
        }
    }

    loadData(){
        //...
        getJSON(url, msg=>{ //get data from server
            if(msg.success && this._mounted){
                //...
                this.timer = setTimeout(()=>{this.loadData()}, 30000); //get data and rerender the component every 30s
            }
        })
    }

    render(){
        //...
    }
}

You can read up more on why that pattern was deprecated here However, doing that naively ends up requiring flags on both the getJSON as well as the subsequent timeout, because basically you need to chain together cancellable promises (where you want to stop any step along the way)

A different paradigm to consider would be to use an observable chain for this. See this blog for details

Share:
10,573
Cinque
Author by

Cinque

Updated on July 16, 2022

Comments

  • Cinque
    Cinque almost 2 years

    Here is the component:

    class ChartComp extends Component{
        constructor(props){
            super(props);
            this.timer = null;
            this.loadData = this.loadData.bind(this);
        }
    
        componentWillMount(){
            this.loadData();
        }
    
        componentWillUnmount(){
            if(this.timer){
                clearTimeout(this.timer);
            }
        }
    
        loadData(){
            //...
            getJSON(url, msg=>{ //get data from server
                if(msg.success){
                    //...
                    this.timer = setTimeout(()=>{this.loadData()}, 30000); //get data and rerender the component every 30s
                }
            })
        }
    
        render(){
            //...
        }
    }
    

    The clearTimeout function will be called before the component is unmounted. But the timer is in an async function, and it starts again after I got response from server. So how can I make clearTimeout work?