Monday, May 20, 2024
 Popular · Latest · Hot · Upcoming
124
rated 0 times [  127] [ 3]  / answers: 1 / hits: 104338  / 9 Years ago, fri, october 2, 2015, 12:00:00

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 &amp; 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 ?


More From » ajax

 Answers
15

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


[#64862] Wednesday, September 30, 2015, 9 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
patienceannel

Total Points: 674
Total Questions: 101
Total Answers: 101

Location: Northern Mariana Islands
Member since Fri, Jan 15, 2021
3 Years ago
patienceannel questions
Fri, Mar 11, 22, 00:00, 2 Years ago
Tue, Oct 20, 20, 00:00, 4 Years ago
Wed, Jul 24, 19, 00:00, 5 Years ago
;