在未挂载的组件上调用 setState [英] Calling setState on an unmounted component
问题描述
在我的很多组件中,我需要做这样的事情:
In a lot of my components I need to do something like this:
handleSubmit() {
this.setState({loading: true})
someAsyncFunc()
.then(() => {
return this.props.onSuccess()
})
.finally(() => this.setState({loading: false}))
}
onSuccess
函数
- 可能是也可能不是承诺(如果是,
loading
应该保持真实,直到它被解决) - 可能会也可能不会卸载组件(它可能会关闭该组件所在的模式,甚至导航到不同的页面)
- may or may not be a promise (if it is,
loading
should stay true until it is resolved) - may or may not unmount the component (it may close the modal this component is in or even navigate to different page)
如果函数卸载组件,this.setState({loading: false})
显然会触发警告 Can't call setState (or forceUpdate) on an unmounted component.
代码>
If the function unmounts the component, this.setState({loading: false})
obviously triggers a warning Can't call setState (or forceUpdate) on an unmounted component.
我的两个问题:
- 有没有一种简单的方法可以避免这个问题?我不想在
componentDidMount
和componentWillUnmount
中设置一些_isMounted
变量,然后在我的大多数组件中需要时检查它,另外我可能下次写这样的东西时忘记这样做了...... - 真的有问题吗?我知道,根据警告,
它表示我的应用程序中存在内存泄漏
,但在这种情况下它不是内存泄漏,是吗?也许忽略警告就可以了......
- Is there a simple way to avoid the issue ? I don't want to set some
_isMounted
variable incomponentDidMount
andcomponentWillUnmount
and then check it when needed in most of my components, plus I may forget to do it next time writing something like this ... - Is it really a problem ? I know that, according to the warning,
it indicates a memory leak in my application
, but it is not a memory leak in this case, is it ? Maybe ignoring the warning would be ok ...
对我来说,第二个问题比第一个问题更重要一点.如果这确实是一个问题并且我无法在未安装的组件上调用 setState
,我可能会自己找到一些解决方法.但我很好奇我是否不能忽略它.
The second question is a little bit more important for me than the first. If this really is a problem and I just can't call setState
on unmounted component, I'd probably find some workaround myself. But I am curious if I can't just ignore it.
问题的实例:
const someAsyncFunc = () => new Promise(resolve => {
setTimeout(() => {
console.log("someAsyncFunc resolving");
resolve("done");
}, 2000);
});
class Example extends React.Component {
constructor(...args) {
super(...args);
this.state = {loading: false};
}
componentDidMount() {
setTimeout(() => this.handleSubmit(), 100);
}
handleSubmit() {
this.setState({loading: true})
someAsyncFunc()
/*
.then(() => {
return this.props.onSuccess()
})
*/
.finally(() => this.setState({loading: false}))
}
render() {
return <div>{String(this.state.loading)}</div>;
}
}
class Wrapper extends React.Component {
constructor(props, ...rest) {
super(props, ...rest);
this.state = {
children: props.children
};
}
componentDidMount() {
setTimeout(() => {
console.log("removing");
this.setState({children: []});
}, 1500)
}
render() {
return <div>{this.state.children}</div>;
}
}
ReactDOM.render(
<Wrapper>
<Example />
</Wrapper>,
document.getElementById("root")
);
.as-console-wrapper {
max-height: 100% !important;
}
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.js"></script>
推荐答案
class myClass extends Component {
_isMounted = false;
constructor(props) {
super(props);
this.state = {
data: [],
};
}
componentDidMount() {
this._isMounted = true;
this._getData();
}
componentWillUnmount() {
this._isMounted = false;
}
_getData() {
axios.get('example.com').then(data => {
if (this._isMounted) {
this.setState({ data })
}
});
}
render() {
...
}
}
这篇关于在未挂载的组件上调用 setState的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!