Javascript 无法在未安装的组件上调用 setState(或 forceUpdate)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/50428842/
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
Can't call setState (or forceUpdate) on an unmounted component
提问by Nikola Stojakovi?
I'm trying to fetch the data from the server after component has been updated but I couldn't manage to do that. As far as I understand componentWillUnmountis called when component is about to be destroyed, but I never need to destroy it so it's useless to me. What would be solution for this? When I should set the state?
我试图在组件更新后从服务器获取数据,但我无法做到这一点。据我所知componentWillUnmount,在组件即将被销毁时调用,但我从来不需要销毁它,所以它对我没用。对此有什么解决方案?我应该什么时候设置状态?
async componentDidUpdate(prevProps, prevState) {
if (this.props.subject.length && prevProps.subject !== this.props.subject) {
let result = await this.getGrades({
student: this.props.id,
subject: this.props.subject
});
this.setState({
subject: this.props.subject,
grades: result
});
}
}
async getGrades(params) {
let response, body;
if (params['subject'].length) {
response = await fetch(apiRequestString.gradesBySubject(params));
body = await response.json();
} else {
response = await fetch(apiRequestString.grades(params));
body = await response.json();
}
if (response.status !== 200) throw Error(body.message);
return body;
}
Full error:
完整错误:
Warning: Can't call setState (or forceUpdate) on an unmounted component. This is a no-op,
but it indicates a memory leak in your application. To fix, cancel all subscriptions and
asynchronous tasks in the componentWillUnmount method.
回答by Steve Vaughan
A common pattern I use in this instance is something along the lines of
我在这个例子中使用的一个常见模式是
componentWillUnmount() {
this.isCancelled = true;
}
And then in the code where you're awaiting an async function to resolve, you would add a check before setting state:
然后在等待异步函数解析的代码中,您将在设置状态之前添加检查:
async componentDidUpdate(prevProps, prevState) {
if (this.props.subject.length && prevProps.subject !== this.props.subject) {
let result = await this.getGrades({
student: this.props.id,
subject: this.props.subject
});
!this.isCancelled && this.setState({
subject: this.props.subject,
grades: result
});
}
}
That will stop any state setting on unmounted/unmounting components
这将停止卸载/卸载组件的任何状态设置
回答by Elia Melfior
The accepted answer works, and is a valid workaround for the problem of calling asynchronous functions in the component rendering methods (getInitialState, componentWillMount, componentDidMount).
接受的答案有效,并且是在组件呈现方法(getInitialState、componentWillMount、componentDidMount)中调用异步函数的问题的有效解决方法。
But a better practice would be to use state management helpers like Redux and Flux and a global store, this might avoid the problem of multiple setStates.
但更好的做法是使用 Redux 和 Flux 等状态管理助手和全局存储,这可能会避免多个 setState 的问题。

