reactjs - 如何处理 React 生命周期方法中的 API 调用?
问题描述
我是 React 新手,尝试设计一个应用程序执行一个简单的 API 调用,更新状态,并根据状态有条件地渲染一组图像。
我对生命周期方法的工作方式感到困惑。根据这个例子,
在 api response 之后渲染 react 组件,API 调用应该在 中处理componentDidMount()
,然后基于状态的 DOM 节点应该在 中处理render()
。
但是,我很困惑,因为 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>
解决方案
对于是否应该在 componentDidMount() 或 componentWillMount() 中进行 API 调用的答案是一个广泛的讨论主题,大多数人建议在 componentDidMount() 中进行 API 调用。
此外,componentWillMount() 方法已被弃用。
对于您的代码没有给出期望的结果 - >这是因为您的 API 调用正在返回一个承诺,并且要从中获得结果,您需要在它之前使用 await。
注意:要在方法中使用 await,方法应该是异步的。为此,请在函数名称前添加 async。
async handlePictures() {
const pictures = await dogs(this.state.breed);
this.setState({
pictures
});
// this.setState(() => ({
// pictures: dogs(this.state.breed)
// }));
}
这是我在代码沙箱上上传的解决方案。看看它。
推荐阅读
- asp.net - 无法将文本框值返回到条件检查输入字符串的格式不正确
- rating - 产品标题下的星级评分错误
- ios - 导航控制器从今天扩展为 nil
- jquery - jQuery如何使用父母的数据属性来修改孩子的内容
- java - LibGdx 数组上的 Java NotSerializable 异常
- swift - UIButton 状态在滚动带有多个部分的 tableview 时发生变化 - Swift
- javascript - HTML CSS 表单的输入字段中的文本之间没有默认空格
- c - C - realloc():遇到无效指针错误
- android - 如何根据screenHeight来区分Layout?
- java - Spring Boot REST CRUD - 如何发布具有一对一关系的实体?