Was ist der richtige Weg, um einen API-Aufruf in React Js durchzuführen?


137

Ich bin kürzlich von Angular zu ReactJs gewechselt. Ich verwende jQuery für API-Aufrufe. Ich habe eine API, die eine zufällige Benutzerliste zurückgibt, die in einer Liste gedruckt werden soll.

Ich bin nicht sicher, wie ich meine API-Aufrufe schreiben soll. Was ist die beste Vorgehensweise dafür?

Ich habe Folgendes versucht, erhalte jedoch keine Ausgabe. Ich bin offen für die Implementierung alternativer API-Bibliotheken, falls erforderlich.

Unten ist mein Code:

import React from 'react';

export default class UserList extends React.Component {    
  constructor(props) {
    super(props);
    this.state = {
      person: []
    };
  }

  UserList(){
    return $.getJSON('https://randomuser.me/api/')
    .then(function(data) {
      return data.results;
    });
  }

  render() {
    this.UserList().then(function(res){
      this.state = {person: res};
    });
    return (
      <div id="layout-content" className="layout-content-wrapper">
        <div className="panel-list">
          {this.state.person.map((item, i) =>{
            return(
              <h1>{item.name.first}</h1>
              <span>{item.cell}, {item.email}</span>
            )
          })}
        <div>
      </div>
    )
  }
}

2
Ich hänge davon ab, welche Statusverwaltungsbibliothek Sie verwenden. Wenn Sie keine verwenden, können Sie Ihre API-Aufrufe in die separate Datei verschieben und API-Funktionen in Ihrer Situation im componentDidMountRückruf aufrufen .
1ven

Sie können fetch()anstelle von jQuery verwenden, wenn Sie jQuery nur zum Ausführen von Ajax-Anforderungen verwenden.
Fred

Warum Jquery verwenden? Jquery ist eine riesige Bibliothek und es ist unnötig
Robin

Fügen Sie hier nur hinzu, dass derzeit useEffectwahrscheinlich der Ort ist, an dem Sie jetzt API-Anrufe tätigen können. Siehe btholt.github.io/complete-intro-to-react-v5/effects
shw

Antworten:


98

In diesem Fall können Sie einen Ajax-Aufruf im Inneren ausführen componentDidMountund dann aktualisierenstate

export default class UserList extends React.Component {
  constructor(props) {
    super(props);

    this.state = {person: []};
  }

  componentDidMount() {
    this.UserList();
  }

  UserList() {
    $.getJSON('https://randomuser.me/api/')
      .then(({ results }) => this.setState({ person: results }));
  }

  render() {
    const persons = this.state.person.map((item, i) => (
      <div>
        <h1>{ item.name.first }</h1>
        <span>{ item.cell }, { item.email }</span>
      </div>
    ));

    return (
      <div id="layout-content" className="layout-content-wrapper">
        <div className="panel-list">{ persons }</div>
      </div>
    );
  }
}

2
Es hat funktioniert, danke. Könnten Sie mir bitte vorschlagen, "welche die beste Bibliothek für ein besseres Staatsmanagement ist"
Raj Rj

3
@ Raj Rj in diesen Tagen denke ich, es ist Redux
Alexander T.

8
Redux ist heutzutage beliebter, sein Stil stammt aus der funktionalen Programmierung. Wenn Sie aus dem OOP-Stil kommen, ist Mobx ( mobxjs.github.io/mobx ) eine ausgezeichnete State-Management-Bibliothek, mit der Sie sich auf das Schreiben von Geschäftscode konzentrieren und letztendlich Ihren Boilerplate-Code reduzieren können
Nhan Tran

25

Vielleicht möchten Sie sich die Flux-Architektur ansehen . Ich empfehle auch, die React-Redux-Implementierung zu lesen . Setzen Sie Ihre API-Aufrufe in Ihre Aktionen ein. Es ist viel sauberer, als alles in die Komponente zu stecken.

Aktionen sind eine Art Hilfsmethode, die Sie aufrufen können, um Ihren Anwendungsstatus zu ändern oder API-Aufrufe auszuführen.


Troper Danke u. Soll ich meine API-bezogenen Aufrufe in separaten Dateien aufbewahren? Und wie nenne ich sie in meiner "Komponentenklasse"? Welche Ordnerstruktur soll ich befolgen? Was ist die beste Vorgehensweise? PS: Ich bin neu darin zu reagieren und stelle diese grundlegenden Fragen.
Raj Rj

Bei der Redux-Implementierung werden Aktionsmethoden in Komponenten injiziert. Diese Methoden werden nun zu Requisiten für Ihre Komponente, die Sie aufrufen können. Sie können das React-Redux-Starter-Kit für die Struktur überprüfen .
Jei Trooper

12

Verwenden Sie die fetchMethode inside componentDidMount, um den Status zu aktualisieren:

componentDidMount(){
  fetch('https://randomuser.me/api/')
      .then(({ results }) => this.setState({ person: results }));
}

11

Diese Diskussion hat eine Weile gedauert und die Antwort von @Alexander T. lieferte einen guten Leitfaden für neuere React wie mich. Und ich werde einige zusätzliche Kenntnisse darüber teilen, wie dieselbe API mehrmals aufgerufen wird, um die Komponente zu aktualisieren. Ich denke, es ist wahrscheinlich ein häufiges Problem, mit dem Neulinge am Anfang konfrontiert sein könnten.

componentWillReceiveProps(nextProps), aus offiziellen Unterlagen :

Wenn Sie den Status als Reaktion auf Requisitenänderungen aktualisieren müssen (z. B. um ihn zurückzusetzen), können Sie this.props und nextProps vergleichen und Statusübergänge mit this.setState () in dieser Methode durchführen.

Wir könnten daraus schließen, dass wir hier Requisiten aus der übergeordneten Komponente verarbeiten, API-Aufrufe durchführen und den Status aktualisieren.

Basis ist das Beispiel von @Alexander T.:

export default class UserList extends React.Component {
  constructor(props) {
    super(props);
    this.state = {person: []};
  }

  componentDidMount() {
   //For our first load. 
   this.UserList(this.props.group); //maybe something like "groupOne"
  }

  componentWillReceiveProps(nextProps) {
    // Assuming parameter comes from url.
    // let group = window.location.toString().split("/")[*indexParameterLocated*];
    // this.UserList(group);

    // Assuming parameter comes from props that from parent component.
    let group = nextProps.group; // Maybe something like "groupTwo" 
    this.UserList(group);
  }

  UserList(group) {
    $.getJSON('https://randomuser.me/api/' + group)
      .then(({ results }) => this.setState({ person: results }));
  }

  render() {
    return (...)
  }
}

Aktualisieren

componentWillReceiveProps() wäre veraltet.

Hier sind nur einige Methoden (alle in Doc ) im Lebenszyklus, die meiner Meinung nach im Allgemeinen mit der Bereitstellung von API zusammenhängen: Geben Sie hier die Bildbeschreibung ein

Unter Bezugnahme auf das obige Diagramm:

  • Stellen Sie die API in bereit componentDidMount()

    Das richtige Szenario für einen API-Aufruf besteht darin, dass der Inhalt (aus der Antwort der API) dieser Komponente statisch ist und componentDidMount()nur einmal ausgelöst wird, während die Komponente bereitgestellt wird. Selbst neue Requisiten werden von der übergeordneten Komponente übergeben oder müssen Aktionen ausführen re-rendering.
    Die Komponente überprüft den Unterschied, um ihn erneut zu rendern, aber nicht erneut bereitzustellen .
    Zitat aus doc :

Wenn Sie Daten von einem Remote-Endpunkt laden müssen, ist dies ein guter Ort, um die Netzwerkanforderung zu instanziieren.


  • Stellen Sie die API in bereit static getDerivedStateFromProps(nextProps, prevState)

Wir sollten feststellen , dass es zwei Arten von Komponenten Aktualisierung , setState() in der aktuellen Komponente würde nicht diese Methode , um Trigger führen, aber erneutes Rendern oder neue Requisiten aus Elternkomponente tun. Wir konnten herausfinden, dass diese Methode auch während der Montage ausgelöst wird.

Dies ist ein geeigneter Ort zum Bereitstellen der API, wenn die aktuelle Komponente wie eine Vorlage verwendet werden soll und die neuen Parameter für die API Requisiten sind, die von der übergeordneten Komponente stammen .
Wir erhalten eine andere Antwort von der API und geben hier eine neue zurück state, um den Inhalt dieser Komponente zu ändern.

Beispiel:
In der übergeordneten Komponente befindet sich eine Dropdown-Liste für verschiedene Fahrzeuge. Diese Komponente muss die Details der ausgewählten Komponente anzeigen.


  • Stellen Sie die API in bereit componentDidUpdate(prevProps, prevState)

Im Unterschied dazu static getDerivedStateFromProps()wird diese Methode unmittelbar nach jedem Rendern mit Ausnahme des anfänglichen Renderns aufgerufen. Wir könnten API-Aufrufe haben und Unterschiede in einer Komponente rendern.

Erweitern Sie das vorherige Beispiel:
Die Komponente zum Anzeigen der Fahrzeugdetails kann eine Liste von Serien dieses Fahrzeugs enthalten. Wenn wir die 2013er Produktion überprüfen möchten, können wir auf das Listenelement klicken oder es auswählen oder ..., um eine erste setState()zu erstellen, die dies widerspiegelt Verhalten (z. B. Hervorheben des Listenelements) in dieser Komponente, und im Folgenden componentDidUpdate()senden wir unsere Anfrage mit neuen Parametern (Status). Nachdem wir die Antwort erhalten haben, werden wir setState()erneut den unterschiedlichen Inhalt der Fahrzeugdetails rendern. Um zu verhindern, dass Folgendes componentDidUpdate()die Unendlichkeitsschleife verursacht, müssen wir den Status vergleichen, indem wir zu prevStateBeginn dieser Methode verwenden, um zu entscheiden, ob wir die API senden und den neuen Inhalt rendern.

Diese Methode könnte wirklich genau wie static getDerivedStateFromProps()bei Requisiten verwendet werden, muss jedoch die Änderungen propsdurch Verwendung von Requisiten bewältigen prevProps. Und wir müssen zusammenarbeiten componentDidMount(), um den ersten API-Aufruf abzuwickeln.

Zitat aus doc :

... Dies ist auch ein guter Ort, um Netzwerkanfragen zu bearbeiten, solange Sie die aktuellen Requisiten mit früheren Requisiten vergleichen ...


10

Ich möchte, dass Sie sich redux http://redux.js.org/index.html ansehen

Sie haben eine sehr gut definierte Art, asynchrone Aufrufe, dh API-Aufrufe, zu verarbeiten. Anstatt jQuery für API-Aufrufe zu verwenden, möchte ich die Verwendung von fetch- oder request- npm-Paketen empfehlen. Fetch wird derzeit von modernen Browsern unterstützt, es steht jedoch auch ein Shim zur Verfügung Serverseite.

Es gibt auch dieses andere erstaunliche Paket Superagent , das viele Optionen beim Erstellen einer API-Anfrage hat und sehr einfach zu bedienen ist.


3

Die Renderfunktion sollte rein sein. Dies bedeutet, dass nur Status und Requisiten zum Rendern verwendet werden. Versuchen Sie niemals, den Status beim Rendern zu ändern. Dies führt normalerweise zu hässlichen Fehlern und verringert die Leistung erheblich. Dies ist auch ein guter Punkt, wenn Sie das Abrufen von Daten trennen und Bedenken in Ihrer React App rendern. Ich empfehle Ihnen, diesen Artikel zu lesen, der diese Idee sehr gut erklärt. https://medium.com/@learnreact/container-components-c0e67432e005#.sfydn87nm


3

Dieser Teil aus der React v16- Dokumentation beantwortet Ihre Frage. Lesen Sie weiter über componentDidMount ():

componentDidMount ()

componentDidMount () wird sofort nach dem Mounten einer Komponente aufgerufen. Die Initialisierung, für die DOM-Knoten erforderlich sind, sollte hier erfolgen. Wenn Sie Daten von einem Remote-Endpunkt laden müssen, ist dies ein guter Ort, um die Netzwerkanforderung zu instanziieren. Diese Methode ist ein guter Ort, um Abonnements einzurichten. Vergessen Sie in diesem Fall nicht, sich in componentWillUnmount () abzumelden.

Wie Sie sehen, wird componentDidMount als der beste Ort und Zyklus für den API-Aufruf angesehen. Sie können auch auf den Knoten zugreifen. Zu diesem Zeitpunkt ist es sicher, den Anruf zu tätigen, die Ansicht zu aktualisieren oder was auch immer Sie tun können, wenn das Dokument fertig ist Mit jQuery sollte es Sie irgendwie an die Funktion document.ready () erinnern, mit der Sie sicherstellen können, dass alles für alles bereit ist, was Sie in Ihrem Code tun möchten ...


3

1) Sie können die F etch-API verwenden , um Daten von Endd Points abzurufen:

Beispiel für das Abrufen der gesamten GithubRuhe für einen Benutzer

  /* Fetch GitHub Repos */
  fetchData = () => {

       //show progress bar
      this.setState({ isLoading: true });

      //fetch repos
      fetch(`https://api.github.com/users/hiteshsahu/repos`)
      .then(response => response.json())
      .then(data => {
        if (Array.isArray(data)) {
          console.log(JSON.stringify(data));
          this.setState({ repos: data ,
                         isLoading: false});
        } else {
          this.setState({ repos: [],
                          isLoading: false  
                        });
        }
      });
  };

2) Andere Alternative ist Axios

Mit axios können Sie den mittleren Schritt der Übergabe der Ergebnisse der http-Anforderung an die .json () -Methode ausschneiden. Axios gibt nur das Datenobjekt zurück, das Sie erwarten würden.

  import axios from "axios";

 /* Fetch GitHub Repos */
  fetchDataWithAxios = () => {

     //show progress bar
      this.setState({ isLoading: true });

      // fetch repos with axios
      axios
          .get(`https://api.github.com/users/hiteshsahu/repos`)
          .then(result => {
            console.log(result);
            this.setState({
              repos: result.data,
              isLoading: false
            });
          })
          .catch(error =>
            this.setState({
              error,
              isLoading: false
            })
          );
}

Jetzt können Sie Daten mit einer dieser Strategien in abrufen componentDidMount

class App extends React.Component {
  state = {
    repos: [],
   isLoading: false
  };

  componentDidMount() {
    this.fetchData ();
  }

In der Zwischenzeit können Sie den Fortschrittsbalken anzeigen, während Daten geladen werden

   {this.state.isLoading && <LinearProgress />}

2

Sie können Daten auch mit Hooks in Ihren Funktionskomponenten abrufen

Vollständiges Beispiel mit API-Aufruf: https://codesandbox.io/s/jvvkoo8pq3

zweites Beispiel: https://jsfiddle.net/bradcypert/jhrt40yv/6/

const Repos = ({user}) => {
  const [repos, setRepos] = React.useState([]);

  React.useEffect(() => {
    const fetchData = async () => {
        const response = await axios.get(`https://api.github.com/users/${user}/repos`);
        setRepos(response.data);
    }

    fetchData();
  }, []);

  return (
  <div>
    {repos.map(repo =>
      <div key={repo.id}>{repo.name}</div>
    )}
  </div>
  );
}

ReactDOM.render(<Repos user="bradcypert" />, document.querySelector("#app"))

1

Der beste Ort und die beste Vorgehensweise für externe API-Aufrufe ist die React Lifecycle-Methode componentDidMount (). Wenn Sie nach der Ausführung des API-Aufrufs den lokalen Status aktualisieren, um einen neuen Aufruf der render () -Methode auszulösen, werden die Änderungen im aktualisierten lokalen Status vorgenommen auf die Komponentenansicht angewendet werden.

Als weitere Option für den ersten Aufruf einer externen Datenquelle in React wird auf die Methode constructor () der Klasse verwiesen . Der Konstruktor ist die erste Methode, die bei der Initialisierung der Komponentenobjektinstanz ausgeführt wird. Sie können diesen Ansatz in den Dokumentationsbeispielen für Komponenten höherer Ordnung sehen .

Die Methoden componentWillMount () und UNSAFE_componentWillMount () sollten nicht für externe API-Aufrufe verwendet werden, da sie veraltet sein sollen. Hier sehen Sie häufige Gründe, warum diese Methode nicht mehr unterstützt wird.

Auf jeden Fall dürfen Sie niemals die Methode render () oder eine direkt von render () aufgerufene Methode als Punkt für einen externen API-Aufruf verwenden. Wenn Sie dies tun, wird Ihre Anwendung blockiert .


0

Eine saubere Möglichkeit besteht darin, einen asynchronen API-Aufruf in componentDidMount mit der Funktion try / catch durchzuführen .

Wenn wir eine API aufrufen, erhalten wir eine Antwort. Dann wenden wir die JSON-Methode darauf an, um die Antwort in ein JavaScript-Objekt zu konvertieren. Dann nehmen wir von diesem Antwortobjekt nur sein untergeordnetes Objekt mit dem Namen "results" (data.results).

Am Anfang haben wir "userList" im Status als leeres Array definiert. Sobald wir den API-Aufruf durchführen und Daten von dieser API empfangen, weisen wir userList die "Ergebnisse" mithilfe der setState-Methode zu .

Innerhalb der Renderfunktion teilen wir mit, dass userList aus dem Status kommt. Da die Benutzerliste ein Array von Objekten ist, ordnen wir sie zu, um ein Bild, einen Namen und eine Telefonnummer jedes Objekts "Benutzer" anzuzeigen. Um diese Informationen abzurufen, verwenden wir die Punktnotation (z. B. user.phone).

HINWEIS : Abhängig von Ihrer API kann Ihre Antwort unterschiedlich aussehen. Console.log die gesamte "Antwort", um zu sehen, welche Variablen Sie benötigen, und weisen Sie sie dann in setState zu.

UserList.js

import React, { Component } from "react";

export default class UserList extends Component {
   state = {
      userList: [], // list is empty in the beginning
      error: false
   };

   componentDidMount() {
       this.getUserList(); // function call
   }

   getUserList = async () => {
       try { //try to get data
           const response = await fetch("https://randomuser.me/api/");
           if (response.ok) { // ckeck if status code is 200
               const data = await response.json();
               this.setState({ userList: data.results});
           } else { this.setState({ error: true }) }
       } catch (e) { //code will jump here if there is a network problem
   this.setState({ error: true });
  }
};

  render() {
  const { userList, error } = this.state
      return (
          <div>
            {userList.length > 0 && userList.map(user => (
              <div key={user}>
                  <img src={user.picture.medium} alt="user"/>
                  <div>
                      <div>{user.name.first}{user.name.last}</div>
                      <div>{user.phone}</div>
                      <div>{user.email}</div>
                  </div>
              </div>
            ))}
            {error && <div>Sorry, can not display the data</div>}
          </div>
      )
}}

0

Es wäre großartig, Axios für die API-Anfrage zu verwenden, die Stornierung, Abfangjäger usw. unterstützt. Neben Axios verwende ich React-Redux für das Zustandsmanagement und Redux-Saga / Redux-Thunk für die Nebenwirkungen.


Dies ist zwar nicht falsch, da die Verwendung von Axios und Redux eine gültige Methode zum Abrufen von Daten und zum Verwalten des Status ist. Sie beantwortet die Frage jedoch nicht wirklich und kommt einem Kommentar näher.
Emile Bergeron
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.