我是React的新手,尝试设计一个应用程序会执行一个简单的API调用,更新状态,并根据状态有条件地渲染一组图像。
我对生命周期方法的工作方式感到困惑。根据这个例子
Rendering react component after api response,应该在componentDidMount()
中处理API调用,然后应该在render()
中处理基于状态的DOM节点。
但是,我很困惑,因为React文档说componentDidMount()
出现在render()
之后。那么在渲染DOM节点之前进行API调用是否有意义?
无论如何,在下面的示例中,默认状态都不会更改。 handlePictures()
应该使用dogs
api调用来生成将在this.state.pictures
中使用的一组图片。但是,这没有发生。当我在本地计算机上运行代码时,当我在this.createIMGs()
方法中运行render()
时发生错误:它说this.state.pictures
是未定义的,这使我猜测API调用从来没有做过。
我正在使用的API在这里:https://dog.ceo/dog-api/documentation/breed 我正在使用页面底部的“来自品种集合的多个图像” API。
//api call
const dogs = async function(breed) {
const dogsAPI = `https://dog.ceo/api/breed/${breed}/images/random/20`;
const dogs = await fetch(dogsAPI);
const json = await dogs.json();
return json.message;
}
//parent component
class DogApp extends React.Component {
constructor() {
super();
this.state = {
pictures: [],
breed: 'hound'
};
}
handleBreed(breed) {
this.setState(() => ({
breed
}));
};
handlePictures() {
this.setState(() => ({
pictures: dogs(this.state.breed)
}));
};
createIMGs() {
this.state.pictures.map((picture) => (
<img src={picture} alt="dog" />
));
};
componentDidMount() {
this.handlePictures();
}
render() {
return (
this.createIMGs();
);
}
}
ReactDOM.render( <DogApp / > , document.getElementById('app'));
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Dogs</title>
<link rel="icon" type="image/png" href="/images/favicon.png">
</head>
<body>
<div id="app"></div>
</body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
</html>
答案 0 :(得分:2)
您应该为此修改handlePictures
函数:
async handlePictures() {
this.setState({
pictures: await dogs(this.state.breed)
});
};
由于dogs
函数正在返回Promise,因此您需要等待它返回数据。
但是,我很困惑,因为React文档说componentDidMount()在render()之后发生。那么在渲染DOM节点之前进行API调用是否有意义?
这已经在社区中进行了很多讨论。这是一篇文章,可以帮助您了解为什么将API调用放在componentDidMount
中:
答案 1 :(得分:2)
有关应在componentDidMount()还是componentWillMount()中进行API调用的答案是一个广泛的讨论主题,大多数人建议在componentDidMount()中进行API调用。
不建议使用componentWillMount()方法。
对于您的代码未给出期望的结果->这是因为您的API调用返回了一个promise,并且要从中获取结果,您需要在它之前使用await。
注意:要在方法中使用等待,该方法应该是异步的。为此,请在函数名称之前添加异步。
async handlePictures() {
const pictures = await dogs(this.state.breed);
this.setState({
pictures
});
// this.setState(() => ({
// pictures: dogs(this.state.breed)
// }));
}
这是我已上传到代码沙箱的解决方案。看看吧。