web-dev-qa-db-fra.com

Utiliser Async / Await avec Axios dans React.js

Suivant

Comment utiliser async/wait avec axios dans react

J'essaie de faire une simple requête get sur mon serveur en utilisant Async/Await dans une application React.js. Le serveur charge un simple JSON à /data qui ressemble à ceci

JSON

{
   id: 1,
   name: "Aditya"
}

Je suis en mesure d’obtenir les données sur mon React App en utilisant la méthode simple jquery ajax get. Cependant, je souhaite utiliser la bibliothèque axios et Async/Await pour respecter les normes ES7. Mon code actuel ressemble à ceci:

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

En utilisant cette approche, j'obtiens l'erreur suivante:

Les objets ne sont pas valides en tant qu'enfant React (trouvé: [promesse de l'objet]). Si vous vouliez rendre une collection d'enfants, utilisez plutôt un tableau.

Est-ce que je ne l'applique pas correctement?

29
Singh

Deux problèmes surgissent:

  1. Votre getData ne renvoie jamais rien. Sa promesse (les fonctions async retournent toujours une promesse) sera résolue avec undefined lorsqu’elle sera résolue.

  2. Le message d'erreur indique clairement que vous essayez de restituer directement la promesse getData renvoie, plutôt que d'attendre sa résolution, puis de restituer la résolution.

L'adressage n ° 1: getData devrait renvoyer le résultat de l'appel de json:

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

Addressig # 2: Nous devrions voir plus de votre code, mais fondamentalement, vous ne pouvez pas faire

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

... parce que cela n'attend pas la résolution. Vous aurez plutôt besoin d'utiliser getData pour définir l'état:

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

... et utiliser cet état lors du rendu:

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

Mise à jour: Maintenant que vous nous avez montré votre code, il vous faudrait faire quelque chose comme ceci:

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

Nouvelle mise à jour: Vous avez indiqué préférer utiliser await dans componentDidMount plutôt que then et catch. Vous feriez cela en imbriquant une fonction async IIFE et en vous assurant que cette fonction ne peut pas être lancée. (componentDidMount elle-même ne peut pas être async, rien ne va dévorer cette promesse.)

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>
        );
    }
}
28
T.J. Crowder

Au cours des derniers mois, je me suis rendu compte que le meilleur moyen de parvenir à cela est:

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

Si vous essayez de faire une demande de publication sur des événements tels que click, appelez alors la fonction getData() sur l'événement et remplacez le contenu de celle-ci de la manière suivante:

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

De plus, si vous faites une requête lorsque le composant est sur le point de charger, remplacez simplement async getData() par async componentDidMount() et modifiez la fonction de rendu de la manière suivante:

render(){
 return (
  <div>{this.state.serverResponse}</div>
 )
}
11
Singh