【发布时间】:2018-12-20 05:11:23
【问题描述】:
我正在调用 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 的样板。
【问题讨论】:
-
在 componentWillUnmount 中添加一个日志行,并在收到此错误之前检查该日志是否打印。
-
能贴出组件代码吗?
-
确实如此。你能从中得出什么结论?
-
@AdamAzad 我正在使用material-ui,所以有相当多的样板,但我会发布它,因为你已经问过了。
-
这意味着您的组件当时不在那里设置状态,这些承诺得到解决。是什么让父组件卸载这个组件?
标签: javascript reactjs promise fetch