我是React的新手。我用它来构建一个非常简单的应用程序。我正在尝试添加一个小功能,但遇到以下错误消息。我还不太了解根本原因。
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.
这就是我想要做的。我的应用程序有一个提供各种API的后端服务器,该API返回JSON。我将React用作调用这些API并呈现它们的前端/客户端。
我有一个名为MyReport
的父组件,该组件使用componentDidMount
来调用API来获取一些数据。然后,在render方法中,我将数据传递到名为MyReportViewer
的另一个组件。该组件还有其他各种子组件,例如允许选择日期的日历,以表格格式显示数据的组件,与图表显示相同数据的组件。
现在,我尝试添加另一个名为MyReportSummary
的子组件,该子组件将与MyReportViewer
呈现的其他组件一起显示。
MyReportSummary
需要调用另一个API来获取一些数据。看起来像这样:
import React, { Component } from 'react';
class MyReportSummary extends Component {
constructor(props) {
super(props);
this.state = {
projectInfo: null,
isLoading: false,
error: null
};
}
componentDidMount() {
this.setState({ isLoading: true });
let projectInfoApi;
projectInfoApi = '/api/projects/' + this.props.projectId;
fetch(projectInfoApi)
.then(response => {
if (response.ok) {
return response.json();
} else {
throw new Error('Encountered problem fetching project info')
}
})
.then(data => this.setState({
projectInfo: data
}))
.catch(fetchError => this.setState({
isLoading: false,
error: fetchError
}));
}
componentWillUnmount() {
// this.setState({
// projectInfo: null
// });
}
render() {
const { isLoading, error } = this.state;
if (error) {
return <p>{error.message}</p>
}
if (isLoading) {
return <p>Loading...</p>
}
return (
<div className="myReportSummary">
Summary of Project name: {projectInfo.name}
Number of events: {this.props.data.length}
</div>
);
}
}
export default MyReportSummary;
我已经读到我需要使用componentWillUnmount
来重置所有内容,但是我不确定在这里究竟需要重置什么,以及为什么在这种情况下需要重置,因为我不认为我正在尝试更改已加载或渲染的组件。
答案 0 :(得分:0)
警告表明您有机会处理获取的响应之前已卸载组件。
您可以将组件的属性保留在状态之外,例如, isMounted
,并在false
中将其设置为componentWillUnmount
,并在获取完成后检查它是否为true
:
示例
class MyReportSummary extends Component {
mounted = true;
state = {
projectInfo: null,
isLoading: true,
error: null
};
componentDidMount() {
fetch(`/api/projects/${this.props.projectId}`)
.then(response => {
if (response.ok) {
return response.json();
} else {
throw new Error("Encountered problem fetching project info");
}
})
.then(data => {
if (this.mounted) {
this.setState({
projectInfo: data
});
}
})
.catch(fetchError => {
if (this.mounted) {
this.setState({
isLoading: false,
error: fetchError
});
}
});
}
componentWillUnmount() {
this.mounted = false;
}
render() {
const { isLoading, error, projectInfo } = this.state;
if (error) {
return <p>{error.message}</p>;
}
if (isLoading) {
return <p>Loading...</p>;
}
return (
<div className="myReportSummary">
Summary of Project name: {projectInfo.name}
Number of events: {this.props.data.length}
</div>
);
}
}