我有一个非常简单的react组件,需要连接到API并检索一些JSON数据,然后将其用于显示一些信息。
在下面的类/组件中,我将mounted
和state
作为属性。我通常使用构造函数保存状态,但在这种情况下,如果将状态移至构造函数,则似乎无法访问渲染器中的数据(projectInfo
)。在渲染器中(行containinig {projectInfo.name}
),出现错误: TypeError:无法读取空的属性“名称”
如何在此类中使用构造函数来保存状态?为什么下面的类起作用,但是当我使用构造函数时却不能起作用?处理这样的事情有什么惯例?
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>
);
}
}
更新:为清楚起见,上述示例代码可以正常工作。我想了解的是,如果我的类看起来像这样,并且具有构造函数的初始化状态,那么我会得到 TypeError 。
class MyReportSummary extends Component {
mounted = true;
constructor(props) {
super(props);
this.state = {
projectInfo: null,
isLoading: false,
error: null
};
}
componentDidMount() {
// same as the previous sample code
}
componentWillUnmount() {
this.mounted = false;
}
render() {
//same as the previous sample code
}
}
正确的州惯例是什么? constructor
是这样做的不正确方法吗?
答案 0 :(得分:1)
像您的第二个示例一样,在构造函数中初始化状态是完全有效的,但是您的两个示例并不相同。您在类属性版本中将isLoading
设置为true
,但在构造函数中将isLoading
设置为false
。
如果error
中的null
并且isLoading
是false
,您将点击渲染方法的最后一部分。由于在您的请求完成之前projectInfo
是null
,所以您将尝试访问name
上的null
并收到错误消息。
将isLoading
设置为true
,它应该可以按预期运行,甚至可以将projectInfo
设置为空对象{}
,但是这样您将无法获得加载指示器。 / p>
class MyReportSummary extends Component {
constructor(props) {
super(props);
this.mounted = true;
this.state = {
projectInfo: {},
isLoading: true,
error: null
};
}
// ...
}