在 React.js 中将 Async/Await 与 Axios 结合使用

IT技术 javascript json reactjs asynchronous ecmascript-2017
2021-03-18 19:09:45

下列的

如何在react中使用 async/await 和 axios

我正在尝试使用 React.js 应用程序中的 Async/Await 向我的服务器发出一个简单的 get 请求。服务器加载一个简单的 JSON /data,看起来像这样

JSON

{
   id: 1,
   name: "Aditya"
}

我能够使用简单的 jquery ajax get 方法将数据获取到我的 React 应用程序。但是,我想利用 axios 库和 Async/Await 来遵循 ES7 标准。我当前的代码如下所示:

class App extends React.Component{
 async getData(){
     const res = await axios('/data');
     console.log(res.json());
 }
 render(){
     return(
         <div>
             {this.getData()}
         </div>
     );
 }
}

使用这种方法我得到以下错误:

对象作为 React 子对象无效(找到:[object Promise])。如果您打算渲染一组子项,请改用数组。

我没有正确实施它吗?

3个回答

两个问题跳出来:

  1. getData从不返回任何东西,所以它的Promise(async函数总是返回一个Promise)undefined如果它不拒绝就会得到满足

  2. 错误消息清楚地表明您正在尝试直接呈现PromisegetData返回,而不是等待它解决然后呈现履行值

解决 #1:getData应该返回调用的结果json

async getData(){
   const res = await axios('/data');
   return await res.json();
}

地址 #2:我们必须查看更多您的代码,但从根本上说,您不能这样做

<SomeElement>{getData()}</SomeElement>

...因为那不会等待决议。您需要改为使用getData来设置状态:

this.getData().then(data => this.setState({data}))
              .catch(err => { /*...handle the error...*/});

...并在渲染时使用该状态:

<SomeElement>{this.state.data}</SomeElement>

更新:现在你已经告诉我们你的代码,你需要做的是这样的:

class App extends React.Component{
    async getData() {
        const res = await axios('/data');
        return await res.json(); // (Or whatever)
    }
    constructor(...args) {
        super(...args);
        this.state = {data: null};
    }
    componentDidMount() {
        if (!this.state.data) {
            this.getData().then(data => this.setState({data}))
                          .catch(err => { /*...handle the error...*/});
        }
    }
    render() {
        return (
            <div>
                {this.state.data ? <em>Loading...</em> : this.state.data}
            </div>
        );
    }
}

进一步更新:您已表示偏好使用awaitincomponentDidMount而不是thenand catch您可以通过在其中嵌套一个asyncIIFE 函数并确保该函数不会抛出来做到这一点。componentDidMount本身不可能async,没有什么会消耗那个Promise。)例如:

class App extends React.Component{
    async getData() {
        const res = await axios('/data');
        return await res.json(); // (Or whatever)
    }
    constructor(...args) {
        super(...args);
        this.state = {data: null};
    }
    componentDidMount() {
        if (!this.state.data) {
            (async () => {
                try {
                    this.setState({data: await this.getData()});
                } catch (e) {
                    //...handle the error...
                }
            })();
        }
    }
    render() {
        return (
            <div>
                {this.state.data ? <em>Loading...</em> : this.state.data}
            </div>
        );
    }
}
它给了我这个错误“在 super() 之前不允许使用‘this’”。所以我添加了 super(); 就在“this.state = {data: null};”之前 这后来导致了一个新的错误:“'getData' is not defined no-undef”
2021-04-23 19:09:45
.catch(err => { /*...处理错误...*/}); 现在执行。它说 res.json() 不是一个函数。
2021-05-04 19:09:45
@Morfsys:我认为这不是确切的错误信息。:-) 我确实说过“这样”。我已经更新了上面的内容,this.getData.
2021-05-12 19:09:45
仅供参考...return res.json()需要return await res.json()在上面的示例中,对吗?如果您在下一行返回它,返回行将立即执行,而不是等待其const res正上方的定义
2021-05-16 19:09:45
@dave4jr:不,你不必——但从代码维护的角度来看,这可能是个好主意,谢谢。“如果你在下一行返回它,返回行将立即执行而不是等待......”不,这是不正确的。returnawait axios('/data')解决之前,行不会执行因此,没有 的代码await会起作用,由getDatabeing创建的promiseasync只是从属于由 返回的promise res.json()但是从代码维护。个人,你是对的,更好await- 因为在对getData.
2021-05-16 19:09:45

根据过去几个月的经验,我意识到实现这一目标的最佳方法是:

class App extends React.Component{
  constructor(){
   super();
   this.state = {
    serverResponse: ''
   }
  }
  componentDidMount(){
     this.getData();
  }
  async getData(){
   const res = await axios.get('url-to-get-the-data');
   const { data } = await res;
   this.setState({serverResponse: data})
 }
 render(){
  return(
     <div>
       {this.state.serverResponse}
     </div>
  );
 }
}

如果您尝试对诸如单击之类的事件发出发布请求,则getData()在事件上调用函数并像这样替换它的内容:

async getData(username, password){
 const res = await axios.post('url-to-post-the-data', {
   username,
   password
 });
 ...
}

此外,如果你做任何请求时,组件即将负载则只需更换async getData()async componentDidMount()和改变渲染功能,如下所示:

render(){
 return (
  <div>{this.state.serverResponse}</div>
 )
}
then并且catch ES2015(又名“ES6”)处理 promise 的方式。async/await是 ES2017(“ES8”)方式。但是你只能await在一个async函数内使用,而makingcomponentWillMount async就是创建一个永远不会被消费的promise。如果您想await改用,那很好,但是您的做法与仅async使用componentWillMount. 在任何情况下,坦率地说,两个月后回来并发布仅调整现有答案而没有归属的答案并不酷。
2021-04-27 19:09:45
这基本上只是我的答案,重新措辞。另外: 1. 不要做componentWillMount一个async函数。React 将忽略返回的 promise。2.除非res.data是一个访问器返回一个promise,否则await在访问时使用它没有任何意义
2021-05-06 19:09:45
我只是试图简化答案。没有进攻,但我认为thencatch不能与Promise采取后续行动的最新标准(ES6)。此外, res.json() 对我不起作用,所以我不得不用 res.data 替换它,该 res.data 带有PromiseGETPOST请求。
2021-05-16 19:09:45
Async/Await with axios 

  useEffect(() => {     
    const getData = async () => {  
      await axios.get('your_url')  
      .then(res => {  
        console.log(res)  
      })  
      .catch(err => {  
        console.log(err)  
      });  
    }  
    getData()  
  }, [])
你确定你可以这样调用 getData() 吗?它还返回一个Promise。
2021-04-28 19:09:45