71 votes

Utiliser Async/Await avec Axios dans React.js

Suivant

Comment utiliser async/await avec axios dans react ?

J'essaie de faire une simple demande d'accès à 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 capable de récupérer les données dans mon application React en utilisant la simple méthode jquery ajax get. Cependant, je veux utiliser la bibliothèque axios et Async/Await pour suivre 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é : [object Promise]). Si vous voulez rendre une collection d'enfants, utilisez plutôt un tableau.

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

0 votes

Render() fonctionne très bien, comme je l'ai clairement indiqué, je suis en mesure d'obtenir des détails lorsque j'utilise $.ajax(). Quel code supplémentaire dois-je ajouter ? Il s'agit d'une simple demande d'accès au serveur utilisant les normes ES7.

0 votes

Idéalement, mettez à jour votre question avec un exécutable exemple minimal reproductible Démontrer le problème en utilisant un placeholder pour l'ajax (par exemple, setTimeout ou similaire), en utilisant les Stack Snippets (le [<>] bouton de la barre d'outils). Stack Snippets prend en charge React, y compris JSX ; voici comment faire .

0 votes

...mais le code ajouté rend les choses absolument claires :-)

92voto

T.J. Crowder Points 285826

Deux points ressortent :

  1. Su getData ne renvoie jamais rien, donc sa promesse ( async qui renvoient toujours une promesse) seront remplies par les fonctions undefined s'il ne rejette pas

  2. Le message d'erreur montre clairement que vous essayez d'effectuer un rendu direct de la promesse. getData plutôt que d'attendre qu'il se stabilise et de rendre la valeur d'accomplissement

Adresse 1 : getData devrait retourner le résultat de l'appel 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>

...car cela n'attend pas la résolution. Il faudrait plutôt 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 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é votre préférence pour l'utilisation de await en componentDidMount plutôt que then y catch . Pour ce faire, vous devez imbriquer un async IIFE et s'assurer que cette fonction ne peut pas être lancée. ( componentDidMount elle-même ne peut pas être async rien ne pourra consommer cette promesse). Par exemple :

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 votes

Il m'a donné cette erreur "'this' n'est pas autorisé avant super()". J'ai donc ajouté super() ; juste avant "this.state = {data : null} ;" ce qui a donné lieu à une nouvelle erreur : "'getData' n'est pas défini no-undef"

0 votes

@Morfsys : Je ne pense pas que ce soit le message d'erreur exact :-) J'ai bien dit " quelque chose comme ce ". J'ai mis à jour ce qui précède, il manquait this. sur getData .

1 votes

.catch(err => { /*...gérer l'erreur...*/}) ; s'exécute maintenant. Il est dit que res.json() n'est pas une fonction.

20voto

Singh Points 628

Au cours de mon expérience de ces derniers mois, j'ai réalisé que le meilleur moyen d'y parvenir 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 post sur des événements tels que le clic, alors appelez getData() sur l'événement et remplacer le contenu de celui-ci comme suit :

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

De plus, si vous effectuez une demande lorsque le composant est sur le point d'être chargé, il suffit de remplacer async getData() con async componentDidMount() et changez la fonction de rendu comme suit :

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

2 votes

C'est en gros ma réponse, reformulée. Aussi : 1. Ne faites pas componentWillMount un async fonction. React ignorera la promesse retournée. 2. Sauf si res.data est un accesseur retournant une promesse, cela n'a aucun sens d'utiliser la fonction await lorsqu'on y accède.

3 votes

J'ai simplement essayé de simplifier la réponse. Ne le prenez pas mal, mais je pense then y catch n'est pas la dernière norme (ES6) de suivi d'une promesse. De plus, res.json() ne fonctionnait pas pour moi et j'ai donc dû le remplacer par res.data qui est accompagné d'une promesse dans le fichier GET o POST demande.

4 votes

then y catch sont la façon ES2015 (alias "ES6") de traiter les promesses. async / await sont la manière ES2017 ("ES8"). Mais vous ne pouvez utiliser await dans un async et en faisant componentWillMount async c'est créer une promesse qui ne sera jamais consommée. Si vous voulez utiliser await à la place, c'est bien, mais vous ne feriez pas ça de la même manière que si vous aviez juste tapé async sur componentWillMount . Quoi qu'il en soit, franchement, revenir deux mois plus tard et poster une réponse qui ne fait que modifier la réponse existante sans la citer, ce n'est pas cool.

9voto

Felipe Corredor Points 161
Async/Await with axios 

  useEffect(() => {     
    const getData = async () => {  
      await axios.get('your_url')  
      .then(res => {  
        console.log(res)  
      })  
      .catch(err => {  
        console.log(err)  
      });  
    }  
    getData()  
  }, [])

1 votes

Vous êtes sûr de pouvoir appeler getData() comme ça ? Il renvoie aussi une promesse.

0voto

MD SHAYON Points 93
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();

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X