In my react component im trying to implement a simple spinner while an ajax request is in progress - im using state to store the loading status.
For some reason this piece of code below in my React component throws this error
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 undefined component.
If I get rid of the first setState call the error goes away.
constructor(props) { super(props); this.loadSearches = this.loadSearches.bind(this); this.state = { loading: false } } loadSearches() { this.setState({ loading: true, searches: [] }); console.log('Loading Searches..'); $.ajax({ url: this.props.source + '?projectId=' + this.props.projectId, dataType: 'json', crossDomain: true, success: function(data) { this.setState({ loading: false }); }.bind(this), error: function(xhr, status, err) { console.error(this.props.url, status, err.toString()); this.setState({ loading: false }); }.bind(this) }); } componentDidMount() { setInterval(this.loadSearches, this.props.pollInterval); } render() { let searches = this.state.searches || []; return (<div> <Table striped bordered condensed hover> <thead> <tr> <th>Name</th> <th>Submit Date</th> <th>Dataset & Datatype</th> <th>Results</th> <th>Last Downloaded</th> </tr> </thead> { searches.map(function(search) { let createdDate = moment(search.createdDate, 'X').format("YYYY-MM-DD"); let downloadedDate = moment(search.downloadedDate, 'X').format("YYYY-MM-DD"); let records = 0; let status = search.status ? search.status.toLowerCase() : '' return ( <tbody key={search.id}> <tr> <td>{search.name}</td> <td>{createdDate}</td> <td>{search.dataset}</td> <td>{records}</td> <td>{downloadedDate}</td> </tr> </tbody> ); } </Table > </div> ); }
The question is why am I getting this error when the component should already be mounted (as its being called from componentDidMount) I thought it was safe to set state once the component is mounted ?
The warning "Can't perform a React state update on an unmounted component" is caused when we try to update the state of an unmounted component. A straight forward way to get rid of the warning is to keep track of whether the component is mounted using an isMounted boolean in our useEffect hook.
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 a useEffect cleanup function.
Warning: Can't call setState (or forceUpdate) 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.
Without seeing the render function is a bit tough. Although can already spot something you should do, every time you use an interval you got to clear it on unmount. So:
componentDidMount() { this.loadInterval = setInterval(this.loadSearches, this.props.pollInterval); } componentWillUnmount () { this.loadInterval && clearInterval(this.loadInterval); this.loadInterval = false; }
Since those success and error callbacks might still get called after unmount, you can use the interval variable to check if it's mounted.
this.loadInterval && this.setState({ loading: false });
Hope this helps, provide the render function if this doesn't do the job.
Cheers
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With