javascript - 如何在promise中的componentDidMount中设置状态而不会出现setState错误
问题描述
我正在调用 api 并使用响应设置状态。我无法在没有看到此错误的情况下调用 setState:如果 setState 发生在承诺之外,则不会发生错误。
如何在不看到此错误的情况下将 API 响应设置为状态?
无法在未安装的组件上调用 setState(或 forceUpdate)
componentDidMount() {
const url = 'https://localhost:8000/api/items'
let items;
fetch(url, {mode: 'cors'})
.then(res => res.json())
.then(
(result) => {
this.setState({
isLoaded: true,
items: result
});
},
(error) => {
this.setState({
isLoaded: true,
error
});
}
)
}
整个组件供参考:
import React, { Component } from 'react'
import PropTypes from 'prop-types';
import { withStyles } from '@material-ui/core/styles';
import GridList from '@material-ui/core/GridList';
import GridListTile from '@material-ui/core/GridListTile';
import GridListTileBar from '@material-ui/core/GridListTileBar';
import ListSubheader from '@material-ui/core/ListSubheader';
import IconButton from '@material-ui/core/IconButton';
import InfoIcon from '@material-ui/icons/Info';
const styles = theme => ({
root: {
display: 'flex',
flexWrap: 'wrap',
justifyContent: 'space-around',
overflow: 'hidden',
backgroundColor: theme.palette.background.paper,
},
icon: {
color: 'rgba(255, 255, 255, 0.54)',
},
});
class ItemList extends Component {
constructor(props) {
super(props)
this.state = {
items: [],
isLoaded: false,
}
this.handleItemClick = this.handleItemClick.bind(this);
}
componentDidMount() {
const url = 'https://localhost:8000/api/items'
let items;
fetch(url, {mode: 'cors'})
.then(res => res.json())
.then(
(result) => {
this.setState({
isLoaded: true,
items: result
});
},
(error) => {
this.setState({
isLoaded: true,
error
});
}
)
}
handleItemClick(id) {
}
handleRenderItems() {
const { classes } = this.props
const { items } = this.state;
return this.state.items.map((item, idx) => {
const id = item.id;
return (
<GridListTile onClick={() => this.handleItemClick(id)} key={idx}>
<img src={item.key_image} alt={item.title} />
<GridListTileBar
title={item.title}
subtitle={<span>${item.rent_price_day}/day</span>}
actionIcon={
<IconButton className={classes.icon}>
<InfoIcon />
</IconButton>
}
/>
</GridListTile>
)
})
}
render() {
const { classes } = this.props;
return (
<div className={classes.root}>
<GridList cols={3} cellHeight={220} className={classes.gridList}>
<GridListTile key="Subheader" cols={3} style={{ height: 'auto' }}>
<ListSubheader component="div">Popular Items</ListSubheader>
</GridListTile>
{this.handleRenderItems()}
</GridList>
</div>
);
}
}
ItemList.propTypes = {
classes: PropTypes.object.isRequired,
};
export default withStyles(styles)(ItemList);
而不是在组件中处理这个 - 我认为在动作创建器中处理对 API 的调用可能更简单,并使用 redux 来存储数据 - 然后在可用时将其发送到组件。无论如何,最好将这些细节隐藏在视图之外。
此外,通常也不会在视图中使用样式对象 - 但它是带有 material-ui 的样板。
解决方案
在您的组件内添加以下内容,
componentDidMount() {
this.isMounted = true;
}
componentWillUnmount() {
this.isMounted = false;
}
仅当 this.isMounted 为 true 时才设置状态。这应该可以解决您的问题,但这不是推荐的模式。请参考https://reactjs.org/blog/2015/12/16/ismounted-antipattern.html
检查包含<ItemList/>
. 如果您<ItemList/>
基于某些条件进行渲染,则问题可能出在这些条件下。
推荐阅读
- javascript - css grid 或 flex 在不指定 item-width 或列数的情况下尽可能多地适应列
- python - 为什么在使用 __getitem__ 迭代时调用了 __len__ 并且没有使用结果?
- typescript - 从接口创建记录,返回类型为原始接口的属性类型
- kubernetes - 从 QUICK(少于 10 秒)Kubernetes cronjob 获取堆栈驱动程序指标的最佳方法是什么?
- php - api-platform 次要版本更新后“无法为类型项目生成 IRI”异常
- office-js - 切换到 Edge 支持的桌面 Web 应用程序查看器后加载项崩溃和体验重定向循环
- css - 手动更改 Bootstrap.css 中的容器宽度是否足够?
- kubernetes - 如何修复 kubernetes nfs 挂载错误没有这样的文件或目录
- python - 我们是否需要 GPU 系统来训练深度学习模型?
- intellij-idea - IntelliJ Idea + Dart 类 - 如何查看特定类的文档注释