Javascript React setState 只能更新一个挂载或挂载的组件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/35345338/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
React setState can only update a mounted or mounting component
提问by erichardson30
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."
“警告:setState(...):只能更新已安装或正在安装的组件。这通常意味着您在未安装的组件上调用了 setState()。这是一个空操作。请检查 ContactPage 组件的代码。”
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.
当我放入调试器时,在加载联系页面时它会点击 componentWillMount()。当我离开联系页面时,它会点击 componentWillUnmount()。当我导航回页面时,它再次点击 componentWillMount() ,然后在点击 onChange(state) 函数时抛出错误。
回答by Felix Kling
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 newfunction. So if you do
.bind
总是返回一个新函数。所以如果你这样做
AppStore.unlisten(this.onChange.bind(this));
then you are trying to remove a listener that doesn't exist (which fails of course). It does notremove the listener you registered with AppStore.listen(this.onChange.bind(this))
那么您正在尝试删除不存在的侦听器(当然失败了)。它并不会删除您注册的监听器AppStore.listen(this.onChange.bind(this))
To solve this, you should bind the handler oncein the constructor:
要解决这个问题,您应该在构造函数中绑定一次处理程序:
this.onChange = this.onChange.bind(this);
and then use AppStore.listen(this.onChange)
and AppStore.unlisten(this.onChange)
.
然后使用AppStore.listen(this.onChange)
和 AppStore.unlisten(this.onChange)
。
回答by Janaka Pushpakumara
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.
我想这会对你有所帮助。
回答by rEjITh
In your case add a ref to your root div and check the ref value before you call setState.
在您的情况下,向您的根 div 添加一个 ref 并在调用 setState 之前检查 ref 值。
Your onChange
method should looks like this:
您的onChange
方法应如下所示:
onChange(state) {
this.refs.yourRef ? this.setState(state) : null;
}
回答by Yuri Nalin
I was struggling with this issue as well for quite a while.
我也在这个问题上挣扎了很长一段时间。
What solved for me was to do as @Felix Kling proposed but also make sure my callback function was declared within the component's class, otherwise you're not able to use the this
prefix, wich was apparently what did the trick for me.
为我解决的是按照@Felix Kling 的建议进行操作,但还要确保在组件的类中声明了我的回调函数,否则您将无法使用this
前缀,这显然对我有用。
Here is an example of what I mean:
这是我的意思的一个例子:
Legal, but doesn't work
合法,但不起作用
function onChange() {
this.setState({ MyState: newState })
}
class MyComponent extends React.Component {
constructor(props) {
super(props);
onChange = onChange.bind(this);
}
componentDidMount() {
window.addEventListener('resize', onChange);
}
componentWillUnmount() {
window.removeEventListener('resize', onChange);
}
render() { ... }
}
Works
作品
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.onChange = this.onChange.bind(this);
}
onChange() {
this.setState({ MyState: newState })
}
componentDidMount() {
window.addEventListener('resize', this.onChange);
}
componentWillUnmount() {
window.removeEventListener('resize', this.onChange);
}
render() { ... }
}
Hope it helps anyone else facing this problem. :)
希望它可以帮助其他任何人面临这个问题。:)