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

拈花ヽ惹草 提交于 2019-11-29 09:18:34

Just add this line of code to the code

export default class MyComponent extends React.Component {
  constructor (props) {
    super(props)
    this.state = {
       initial: 'state',
       some: ''          // <-------  this line
    }
   this.clickMe = this.clickMe.bind(this)
  }

 clickMe () {
   this.setState({
     some: 'new state'
   })
  }

 render () {
   return (
     <div>
       <button onClick={this.clickMe}>click</button>
     </div>
   );
  }
}

As @Amida mentioned, hot-loader seems to be the issue. Whoever is using

app.UseWebpackDevMiddleware(new WebpackDevMiddlewareOptions
{
    HotModuleReplacement = true,
    ReactHotModuleReplacement = true
});

in Startup.cs, remove it and the issue will disappear. I don't know why, but this is my current workaround.

EDIT:

Update of "react-hot-loader" and "webpack-hot-middleware" to latest versions fixed the issue

If this error is happening in one of your tests, you might need to render the component to an element before accessing it (i.e. simply doing let app = new App; is not enough). Rendering will effectively mount the component and its children, as explained in this other answer and then you will be able to use the result object to perform operations without triggering the setState error. A simple App.test.js example:

import App from './App';

it('renders without crashing', () => {
  const div = document.createElement('div');
  ReactDOM.render(<App />, div); // <-- App component mounted here
  // without JSX: ReactDOM.render(React.createElement(App), div)
  ReactDOM.unmountComponentAtNode(div);
});

test('array length decreased after removal', () => {
  const div = document.createElement('div');
  let app = ReactDOM.render(<App />, div); // <-- App component mounted here
  const origArrLen = app.state.arr.length;

  app.removeAtIndex(0);
  expect(app.state.arr.length).toEqual(origArrLen - 1);
  ReactDOM.unmountComponentAtNode(div);
});

Where the App component could have:

class App extends Component {
  state = {
    arr: [1,2,3]
  };

  removeAtIndex = index => {
    const { arr } = this.state;
    this.setState({ arr: arr.filter((el, i) => i !== index) });
  };
  // render() { return ( ... ) }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!