Utilisez Async / wait avec Axios dans React.js

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

JSON

{
   id: 1,
   name: "Aditya"
}

je suis capable d'obtenir les données de mon application React en utilisant la méthode simple jQuery ajax get. Cependant, je veux faire usage de la bibliothèque axios et Async / en attente de suivre les normes ES7. Mon code 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'ai le erreur:

les Objets ne sont pas valides comme Réagir enfant (trouvé: [objet de la Promesse]). Si que vous vouliez rendre une collection d'enfants, utiliser un tableau à la place.

est-ce que je ne l'implémente pas correctement?

17
demandé sur Felix Kling 2017-10-13 18:33:00

2 réponses

Deux questions sauter:

  1. getData ne retourne jamais rien, donc sa promesse (async renvoient toujours une promesse de résoudre avec undefined quand il se résout

  2. le message d'erreur indique clairement que vous essayez de rendre directement la promesse getData retourne, plutôt que d'attendre qu'il se résolve et de rendre ensuite la résolution

Adressage #1: getData devrait retour le résultat de l'appel à json:

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

Addressig #2: nous aurions à voir plus de votre code, mais fondamentalement, vous ne pouvez pas faire

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

...parce que ça n'attend pas la résolution. Vous auriez besoin au lieu d'utiliser getData pour définir l'état:

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

...et l'utilisation que l'état lors du rendu:

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

mise à Jour: Maintenant que vous avez montré votre code, vous devez 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>
        );
    }
}

Plus de mise à jour: vous avez indiqué une préférence pour awaitcomponentDidMount plutôt que then et catch. Vous feriez cela en nichant un async la vie fonctionne à l'intérieur de celui-ci et de s'assurer que cette fonction ne peut pas jeter. (componentDidMount lui-même ne peut pas être async, rien ne consume cette promesse.) 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>
        );
    }
}
17
répondu T.J. Crowder 2018-05-10 05:57:46

Dans mon expérience au cours des derniers mois, j'ai réalisé que la meilleure façon 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 requête post sur des événements tels que click, alors appelez getData() fonction de l'événement et de 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 faites une demande lorsque le composant est sur le point de se charger, remplacez simplement async getData()async componentDidMount() et modifier le rendu de la fonction comme ceci:

render(){
 return (
  <div>{this.state.serverResponse}</div>
 )
}
6
répondu Aditya 2018-07-29 23:24:09