kennet postigo kennet postigo - 1 month ago 27
React JSX Question

React throwing error on mounting or mounted component may be due to rapid and frequent calls to setState()

I've been working on a component that needs to keep track of the width of the page whenever it resizes. However I'm able to do that but react keeps throwing me an error.

this is the error it throws:


warning.js:36 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 Nav component.




The code that the stack trace points to that is causing the error is the
handleResize()
method on the
Nav
Component. After doing a bit of searching and googling I found that the cause is that
setState()
is being called before the component is mounted. Which is odd because the event listeners is being registered in
componentDidMount()
. An article suggested using
componentWillMount
No cigar. I'm not exactly sure why this is happening. Maybe because of the amount of resizing going on at such a fast pace?

handleResize() {
this.setState((prevState, currProps) => ({
height: window.innerHeight,
width: window.innerWidth
}));
if (this.props.showMenu === undefined) {
if (this.state.width > (this.props.breakPoint || 767) && this.state.showMenu) {
this.setState((prevState, currProps) => ({
showMenu: false,
}));
}
} else {
if (this.state.width > (this.props.breakPoint || 767) && this.props.showMenu) {
this.props.closeMenu();
}
}
}

componentDidMount () {
window.addEventListener('resize', this.handleResize.bind(this));
}

componentWillUnmount () {
window.removeEventListener('resize', this.handleResize.bind(this))
}



Answer

this.handleResive.bind(this) creates a new function, which means window.removeEventListener('resize', this.handleResize.bind(this)) is also creating a new function and not passing the same function that you added in the first place. This means the one you created with bind and added previously is not being removed, since it is not the same function (even though it will behave exactly the same).

One way to resolve this is to store the function before adding it:

componentDidMount () {
    const resizeHandler = this.handleResize.bind(this);
    this.setState({resizeHandler});
    window.addEventListener('resize', resizeHandler);
}

componentWillUnmount () {
    window.removeEventListener('resize', this.state.resizeHandler);
    //you could cleanup state here but it's not necessary
}

If anyone has a better way to store the event handling function please chime in.