ssss
ssss

Reputation: 21

Warning: setState(...): Can only update a mounted or mounting component. With timer

Warning: setState(...): Can only update a mounted or mounting component. This usually means you called setState() on an unmounted component. This is a no-op. Please check the code for the Clock component.

Why is this error keeping being displayed ?? When I log out from my app this warning starts to appear on the console. Could anybody explain why that happens ?

const Clock = React.createClass({

    getInitialState() {
        return {
            currentTime: moment.utc().format(formatter)
        };
    },

    componentDidMount: function() {
        const tickId = setInterval(this.tick, 1000);
        this.setState({tickId: tickId});
    },

    componentWillUnmount: function() {
        clearInterval(this.state.tickId);
    },

    tick: function() {
        this.setState({
            currentTime: moment.utc().format(formatter)
        });
    },

    render() {
        return <span>{this.state.currentTime}</span>;
    }
});

Upvotes: 0

Views: 166

Answers (2)

Rick Jolly
Rick Jolly

Reputation: 3009

No need to store the tickId in state.

componentDidMount: function() {
    this.tickId = setInterval(this.tick, 1000);
},

componentWillUnmount: function() {
    clearInterval(this.tickId);
}

Upvotes: 1

Chase DeAnda
Chase DeAnda

Reputation: 16441

I've ran into a similar issue before. What was happening in my case, I was correctly canceling the interval, but there would be times where it would cancel after already calling the function again. What I needed was a way to know if the component was still mounted or not. Unfortunately, React doesn't expose a components mounted state (or at least not easily). So I ended up keeping track of the mounted state myself and then checking if the component was still mounted when calling my interval function.

const Clock = React.createClass({

    getInitialState() {
        return {
            currentTime: moment.utc().format(formatter)
        };
    },

    componentDidMount: function() {
        this._isMounted = true;
        const tickId = setInterval(this.tick, 1000);
        this.setState({tickId: tickId});
    },

    componentWillUnmount: function() {
        this._isMounted = false;
        clearInterval(this.state.tickId);
    },

    tick: function() {
        if(this._isMounted) {
            this.setState({
                currentTime: moment.utc().format(formatter)
            });
        }
    },

    render() {
        return <span>{this.state.currentTime}</span>;
    }
});

Upvotes: 1

Related Questions