Use Async/Await with Axios in React.js

后端 未结 2 654
臣服心动
臣服心动 2020-12-07 16:52

Following

How to use async/await with axios in react

I am trying to make a simple get request to my server using Async/Await in a React.js

相关标签:
2条回答
  • 2020-12-07 17:19

    Two issues jump out:

    1. Your getData never returns anything, so its promise (async functions always return a promise) will resolve with undefined when it resolves

    2. The error message clearly shows you're trying to directly render the promise getData returns, rather than waiting for it to resolve and then rendering the resolution

    Addressing #1: getData should return the result of calling json:

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

    Addressig #2: We'd have to see more of your code, but fundamentally, you can't do

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

    ...because that doesn't wait for the resolution. You'd need instead to use getData to set state:

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

    ...and use that state when rendering:

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

    Update: Now that you've shown us your code, you'd need to do something like this:

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

    Futher update: You've indicated a preference for using await in componentDidMount rather than then and catch. You'd do that by nesting an async IIFE function within it and ensuring that function can't throw. (componentDidMount itself can't be async, nothing will consume that promise.) E.g.:

    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>
            );
        }
    }
    
    0 讨论(0)
  • 2020-12-07 17:19

    In my experience over the past few months, I've realized that the best way to achieve this is:

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

    If you are trying to make post request on events such as click, then call getData() function on the event and replace the content of it like so:

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

    Furthermore, if you are making any request when the component is about to load then simply replace async getData() with async componentDidMount() and change the render function like so:

    render(){
     return (
      <div>{this.state.serverResponse}</div>
     )
    }
    
    0 讨论(0)
提交回复
热议问题