Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React setState can only update a mounted or mounting component

Tags:

I am getting the following warning

"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 ContactPage component."

When I initially go to the contact page the firs time it is fine. Then if I navigate off the page and go back the warning is thrown.

Contact page component :

import React, { Component, PropTypes } from 'react'; import AppStore from '../../stores/AppStore'; import AppActions from '../../actions/AppActions'; import DataContent from './DataContent';  const title = 'Contact Us';   class ContactPage extends Component {      constructor(props) {         super(props);         this.state = AppStore.getState();         AppActions.getData();     }    static contextTypes = {     onSetTitle: PropTypes.func.isRequired,   };    componentWillMount() {     this.context.onSetTitle(title);     AppStore.listen(this.onChange.bind(this)); }  componentWillUnmount() {     AppStore.unlisten(this.onChange.bind(this)); }  onChange(state) {     this.setState(state); }  renderData() {     return this.state.data.map((data) => {         return (             <DataContent key={data.id} data={data} />         )     }) }    render() {     return (       <div className={s.root}>         <div className={s.container}>           <h1>{title}</h1>           <div>               { this.renderData() }           </div>         </div>       </div>     ); }  }  export default ContactPage; 

When I put debuggers in, on load of contact page it hits componentWillMount(). When I leave the contact page it hits componentWillUnmount(). When I navigate back to the page it hits componentWillMount() again and then throws the error when it hits the onChange(state) function.

like image 376
erichardson30 Avatar asked Feb 11 '16 16:02

erichardson30


People also ask

Can only update a mounted or mounting component?

Warning: Can only update a mounted or mounting component. This usually means you called setState, replaceState, or forceUpdate on an unmounted component. This is a no-op. Warning: Can't call setState (or forceUpdate) on an unmounted component.

Can set state on unmounted component?

Seeing called setState() on an unmounted component in your browser console means the callback for an async operation is still running after a component's removed from the DOM. This points to a memory leak caused by doing redundant work which the user will never benefit from.

Can't call setState on a component that is not yet mounted React?

This error usually happens when you call the React setState method in a Class component's constructor. The reason is that the component state is not yet initialized when the constructor is called.

Can't perform a React state update on an unmounted component React hooks?

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.


2 Answers

The issue is that the listener of the previous component instance is still registered. And because the previous instance isn't mounted anymore, you get that error.

.bind always returns a new function. So if you do

AppStore.unlisten(this.onChange.bind(this)); 

then you are trying to remove a listener that doesn't exist (which fails of course). It does not remove the listener you registered with AppStore.listen(this.onChange.bind(this))


To solve this, you should bind the handler once in the constructor:

this.onChange = this.onChange.bind(this); 

and then use AppStore.listen(this.onChange) and AppStore.unlisten(this.onChange).

like image 119
Felix Kling Avatar answered Oct 24 '22 04:10

Felix Kling


Before the change, state check component is mounted.

render() {    return (      <div ref="root" className={s.root}>        // ----      </div>    )};   onChange(state) {    if(this.refs.root) {      this.setState(state);    }  } 

I think this will help to you.

like image 33
Janaka Pushpakumara Avatar answered Oct 24 '22 04:10

Janaka Pushpakumara