【问题标题】:Use Async/Await with Axios in React.js在 React.js 中将 Async/Await 与 Axios 一起使用
【发布时间】:2018-03-25 19:01:53
【问题描述】:

关注

How to use async/await with axios in react

我正在尝试在 React.js 应用程序中使用 Async/Await 向我的服务器发出简单的获取请求。 服务器在/data 加载一个简单的 JSON,如下所示

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])。如果 你的意思是渲染一组孩子,使用一个数组来代替。

我没有正确实现它吗?

【问题讨论】:

  • render() 工作得很好,因为我清楚地提到当我使用 $.ajax() 时可以获取详细信息。我应该添加什么额外的代码?这是一个使用 ES7 标准对服务器的简单 get 请求。
  • 理想情况下,使用 Stack Snippets (the [&lt;&gt;] 工具栏按钮)。 Stack Snippets 支持 React,包括 JSX; here's how to do one.
  • ...但是添加的代码绝对让事情变得清晰。 :-)
  • 仅供参考,async/await 是 ES2017 的一部分,不是 ES7 (ES2016)。
  • 感谢您提供的信息。

标签: javascript json reactjs asynchronous ecmascript-2017


【解决方案1】:

跳出两个问题:

  1. 你的getData 永远不会返回任何东西,所以如果它不拒绝,它的承诺(async 函数总是返回一个承诺)将通过undefined 实现

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

寻址#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>
        );
    }
}

进一步更新:您已表明在componentDidMount 中使用await 而不是thencatch 的偏好。您可以通过在其中嵌套 async IIFE 函数并确保该函数不会抛出来做到这一点。 (componentDidMount 本身不能是 async,没有任何东西会消耗这个承诺。)例如:

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>
        );
    }
}

【讨论】:

  • 它给了我这个错误“'this' is not allowed before super()”。所以我添加了 super();就在“this.state = {data: null};”之前后来导致了一个新错误:“'getData' is not defined no-undef”
  • @Morfsys:我认为这不是确切的错误信息。 :-) 我确实说过“类似这样的”。我已经更新了上面的内容,在getData 上缺少this.
  • .catch(err => { /*...处理错误...*/});现在执行。它说 res.json() 不是函数。
  • 仅供参考...return res.json() 在上面的示例中需要为return await res.json(),对吗?如果您在下一行返回它,返回行将立即执行,而不是等待其上方的const res 定义。
  • @dave4jr:不,您不必这样做——但从代码维护的角度来看,这可能是一个好主意,谢谢。 “如果您在下一行返回它,返回行将立即执行而不是等待......” 不,这是不正确的。在await axios('/data') 解决之前,return 行不会执行。所以没有await 的代码可以工作,getData 创建的承诺是async 将只是从属于res.json() 返回的承诺。但从代码维护。个人,你是对的,最好 await 它 - 因为在更改 getData 时很容易搞砸。
【解决方案2】:

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

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>
 )
}

【讨论】:

  • 这基本上只是我的回答,重新措辞。另外: 1. 不要将componentWillMount 设为async 函数。 React 将忽略返回的承诺。 2.除非res.data是一个返回promise的访问器,否则访问时使用await没有任何意义。
  • 我只是试图简化答案。无意冒犯,但我认为 thencatch 不是跟进承诺的最新标准 (ES6)。此外, res.json() 对我不起作用,所以我不得不用 res.data 替换它,并附上GETPOST 请求中的承诺。
  • thencatch ES2015(又名“ES6”)处理承诺的方式。 async/await 是 ES2017 ("ES8") 方式。但是你只能在async 函数中使用await,而使componentWillMount async 是在创建一个永远不会被消耗的promise。如果您想改用await,那很好,但您的做法与在componentWillMount 上打async 不同。无论如何,坦率地说,两个月后回来并发布一个只调整现有答案而不注明出处的答案并不酷。
【解决方案3】:
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() 吗?它还返回一个承诺。
【解决方案4】:
const axios = require('axios').default;

const sendGetRequest = async () => {
    try {
        const resp = await axios.get('https://jsonplaceholder.typicode.com/posts', {
            headers: {
                'authorization': 'Bearer YOUR_JWT_TOKEN_HERE'
            }
        });

        console.log(resp.data);
    } catch (err) {
        // Handle Error Here
        console.error(err);
    }
};

sendGetRequest();

【讨论】:

    猜你喜欢
    • 2018-09-03
    • 2017-11-05
    • 2019-04-15
    • 2014-06-19
    • 2018-01-14
    • 2018-09-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多