我该如何处理React生命周期方法中的API调用?

时间:2019-04-24 03:46:08

标签: reactjs

我是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>

2 个答案:

答案 0 :(得分:2)

您应该为此修改handlePictures函数:

async handlePictures() {
  this.setState({
    pictures: await dogs(this.state.breed)
  });
};

由于dogs函数正在返回Promise,因此您需要等待它返回数据。

  

但是,我很困惑,因为React文档说componentDidMount()在render()之后发生。那么在渲染DOM节点之前进行API调用是否有意义?

这已经在社区中进行了很多讨论。这是一篇文章,可以帮助您了解为什么将API调用放在componentDidMount中:

https://hackernoon.com/where-to-integrate-api-calls-in-reactjs-componentwillmount-vs-componentdidmount-710085dc05c3

答案 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)
  // }));
}

这是我已上传到代码沙箱的解决方案。看看吧。

Edit 40jwxmwv59