Verwenden Sie Async/Await mit Axios in React.js

Lesezeit: 6 Minuten

Singhs Benutzeravatar
Singh

Folgend

Wie man async/await mit Axios in React verwendet

Ich versuche, mit Async/Await in einer React.js-App eine einfache Get-Anfrage an meinen Server zu stellen. Der Server lädt ein einfaches JSON unter /data was so aussieht

JSON

{
   id: 1,
   name: "Aditya"
}

Ich kann die Daten mit der einfachen jquery ajax get-Methode an meine React-App übertragen. Ich möchte jedoch die Axios-Bibliothek und Async/Await verwenden, um den ES7-Standards zu folgen. Mein aktueller Code sieht so aus:

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

Mit diesem Ansatz erhalte ich den folgenden Fehler:

Objekte sind als React-Kind nicht gültig (gefunden: [object Promise]). Wenn Sie eine Sammlung von untergeordneten Elementen rendern wollten, verwenden Sie stattdessen ein Array.

Implementiere ich es nicht richtig?

  • render() funktioniert einwandfrei, da ich deutlich erwähnt habe, dass ich Details erhalten kann, wenn ich $.ajax() verwende. Welchen zusätzlichen Code soll ich hinzufügen? Dies ist eine einfache Get-Anforderung an den Server unter Verwendung von ES7-Standards.

    – Singh

    13. Oktober 2017 um 15:38 Uhr


  • Aktualisieren Sie Ihre Frage im Idealfall mit a lauffähig minimal reproduzierbares Beispiel, das das Problem mit einem Platzhalter für das Ajax demonstriert (z. B. setTimeout oder ähnliches), mit Stack Snippets (the [<>] Symbolleistenschaltfläche). Stack Snippets unterstützen React, einschließlich JSX; Hier ist, wie man es macht.

    – TJ Crowder

    13. Oktober 2017 um 15:43 Uhr

  • …aber der hinzugefügte Code macht die Dinge absolut klar. 🙂

    – TJ Crowder

    13. Oktober 2017 um 15:48 Uhr

  • Zu Ihrer Information, async/await ist Teil von ES2017, nicht ES7 (ES2016).

    – Felix Klinge

    13. Oktober 2017 um 17:20 Uhr

  • Danke für die Information.

    – Singh

    13. Oktober 2017 um 17:24 Uhr

Benutzeravatar von TJ Crowder
TJ Crowder

Zwei Probleme springen heraus:

  1. Dein getData gibt nie etwas zurück, also sein Versprechen (async Funktionen geben immer ein Promise zurück) erfüllt werden undefined wenn es nicht ablehnt

  2. Die Fehlermeldung zeigt deutlich, dass Sie versuchen, das Versprechen direkt zu machen getData zurückgibt, anstatt darauf zu warten, dass es sich begleicht, und dann den Erfüllungswert zu erbringen

Adressierung #1: getData sollte Rückkehr das Ergebnis des Anrufs json:

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

Adresse 2: Wir müssten mehr von Ihrem Code sehen, aber im Grunde können Sie das nicht

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

…denn das wartet nicht auf die Auflösung. Sie müssten stattdessen verwenden getData Zustand setzen:

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

… und diesen Zustand beim Rendern verwenden:

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

Aktualisieren: Jetzt, da Sie uns Ihren Code gezeigt haben, müssen Sie tun etwas wie Dies:

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

Weiteres Update: Sie haben eine Präferenz für die Verwendung angegeben await in componentDidMount statt then und catch. Sie würden das tun, indem Sie ein verschachteln async IIFE-Funktion darin und stellt sicher, dass die Funktion nicht werfen kann. (componentDidMount selbst kann nicht sein asyncnichts wird dieses Versprechen verbrauchen.) Bsp.:

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

  • Es gab mir diesen Fehler “‘this’ ist vor super() nicht erlaubt”. Also habe ich super(); direkt vor “this.state = {data: null};” was später zu einem neuen Fehler führte: “‘getData’ is not defined no-undef”

    – Singh

    13. Oktober 2017 um 15:54 Uhr

  • @Morfsys: Ich glaube nicht, dass das die genaue Fehlermeldung ist. 🙂 Ich sagte “etwas wie this”. Ich habe das oben aktualisiert, fehlte this. an getData.

    – TJ Crowder

    13. Oktober 2017 um 15:57 Uhr

  • .catch(err => { /*…den Fehler behandeln…*/}); wird jetzt ausgeführt. Es besagt, dass res.json() keine Funktion ist.

    – Singh

    13. Oktober 2017 um 16:16 Uhr


  • Nur zur Info… return res.json() müsste sein return await res.json() im obigen Beispiel, richtig? Wenn Sie es in der nächsten Zeile zurückgeben, wird die Rückgabezeile sofort ausgeführt, anstatt darauf zu warten, von definiert zu werden const res genau darüber.

    – dave4jr

    9. Mai 2018 um 22:13 Uhr

  • @dave4jr: Nein, das musst du nicht — aber es könnte aus Sicht der Code-Wartung eine gute Idee sein, danke. “Wenn Sie es in der nächsten Zeile zurückgeben, wird die Rückgabezeile sofort ausgeführt, anstatt zu warten …” Nein, das ist falsch. Das return Zeile wird nicht ausgeführt, bis die await axios('/data') beschließt. Also der Code ohne die await würde funktionieren, das Versprechen erstellt von getData Sein async würde nur demjenigen versklaven, der zurückgekehrt ist res.json(). Aber von einer Code-Wartung. pers., du hast recht, besser zu await es — weil es leicht wäre, es durcheinander zu bringen, wenn man Änderungen daran vornimmt getData.

    – TJ Crowder

    10. Mai 2018 um 5:59 Uhr

Singhs Benutzeravatar
Singh

Nach meiner Erfahrung in den letzten Monaten habe ich erkannt, dass der beste Weg, dies zu erreichen, folgender ist:

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

Wenn Sie versuchen, bei Ereignissen wie Klick eine Post-Anfrage zu stellen, dann rufen Sie an getData() Funktion für das Ereignis und ersetzen Sie den Inhalt wie folgt:

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

Wenn Sie eine Anfrage stellen, wenn die Komponente gerade geladen wird, ersetzen Sie sie einfach async getData() mit async componentDidMount() und ändern Sie die Renderfunktion wie folgt:

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

  • Dies ist im Grunde nur meine Antwort, umformuliert. Außerdem: 1. Nicht machen componentWillMount ein async Funktion. React ignoriert das zurückgegebene Promise. 2. Es sei denn res.data ein Accessor ist, der ein Versprechen zurückgibt, macht es keinen Sinn, ihn zu verwenden await beim Zugriff darauf.

    – TJ Crowder

    18. Dezember 2017 um 8:13 Uhr

  • Ich habe lediglich versucht, die Antwort zu vereinfachen. Nichts für ungut, aber ich denke then und catch ist nicht der neueste Standard (ES6) für das Nachfassen mit einem Versprechen. Außerdem funktionierte res.json() bei mir nicht und ich musste es durch res.data ersetzen, das mit einem Versprechen einhergehtGET oder POST Anfrage.

    – Singh

    18. Dezember 2017 um 8:34 Uhr

  • then und catch sind die ES2015 (alias “ES6”) Art, mit Versprechen umzugehen. async/await sind die ES2017 (“ES8”) Weg. Aber Sie können nur verwenden await innerhalb eines async Funktion und Herstellung componentWillMount async schafft ein Versprechen, das niemals eingelöst wird. Wenn Sie verwenden möchten await stattdessen ist das in Ordnung, aber Sie würden das anders machen als nur zu schlagen async an componentWillMount. Ehrlich gesagt ist es auf jeden Fall nicht cool, zwei Monate später wiederzukommen und eine Antwort zu posten, die nur die vorhandene ohne Zuschreibung optimiert.

    – TJ Crowder

    18. Dezember 2017 um 8:42 Uhr


 async fetchCatFacts() {
    await axios.get("//localhost:8082/api_v1/orders", {})
        .then((response) => {

          this.catFacts = response.data.data;
          console.log("resp", response.data);
        });

1434550cookie-checkVerwenden Sie Async/Await mit Axios in React.js

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy