[英]Cannot fetch data from an API using componentDidMount: Can't call setState (or forceUpdate) on an unmounted component
I'm relatively new to React. 我是React的新手。 I've used it for building a very simple app.
我用它来构建一个非常简单的应用程序。 I'm trying to add a small feature, but running into following error message.
我正在尝试添加一个小功能,但遇到以下错误消息。 I don't quite understand the root cause yet.
我还不太了解根本原因。
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.
Here's what I'm trying to do. 这就是我想要做的。 My app has a backend server that provides various APIs, which returns JSON.
我的应用程序有一个提供各种API的后端服务器,该API返回JSON。 I'm using React as frontend/client that calls those APIs and renders them.
我正在使用React作为调用这些API并呈现它们的前端/客户端。
I have a Parent component named MyReport
which uses componentDidMount
to call an API to fetch some data. 我有一个名为
MyReport
的父组件MyReport
该componentDidMount
使用componentDidMount
来调用API来获取一些数据。 Then in the render method, I pass the data to another component named MyReportViewer
. 然后在render方法中,将数据传递到另一个名为
MyReportViewer
组件。 This component has various other child components such as a Calendar that allows selecting date, a component that shows the data in a table format, a component that shows the same data as a chart. 该组件具有各种其他子组件,例如允许选择日期的日历,以表格格式显示数据的组件,与图表显示相同数据的组件。
Now I'm trying to add another child component called MyReportSummary
that will be displayed alongside the other components rendered by MyReportViewer
. 现在,我试图添加另一个名为
MyReportSummary
子组件,该子组件将与MyReportViewer
呈现的其他组件一起显示。
MyReportSummary
needs to call another API to fetch some data. MyReportSummary
需要调用另一个API来获取一些数据。 This is what it looks like: 看起来是这样的:
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;
I've read that I need to use componentWillUnmount
to reset everything, but I'm not sure what exactly I need to reset here and why in this case I need to do it because I don't think I'm trying to change the component after it's been loaded or rendered already. 我已经读到我需要使用
componentWillUnmount
来重置所有内容,但是我不确定在这里究竟需要重置什么,以及为什么在这种情况下需要这么做,因为我不认为我想更改组件已经加载或呈现后。
The warning indicates that your component has been unmounted before you get a chance to handle the response of your fetch. 该警告表明您有机会处理获取的响应之前已卸载组件。
You can keep a property on your component outside of state called eg isMounted
and set that to false
in componentWillUnmount
and check if it's true
when your fetch has completed: 您可以将组件的属性保留在状态之外,例如
isMounted
并在componentWillUnmount
isMounted
其设置为false
,并在获取完成后检查它是否为true
:
Example 例
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>
);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.