Quelle est la bonne façon de faire un appel API dans react js?


137

Je suis récemment passé d'Angular à ReactJs. J'utilise jQuery pour les appels API. J'ai une API qui renvoie une liste d'utilisateurs aléatoire qui doit être imprimée dans une liste.

Je ne sais pas comment écrire mes appels API. Quelle est la meilleure pratique pour cela?

J'ai essayé ce qui suit mais je n'obtiens aucune sortie. Je suis ouvert à la mise en œuvre de bibliothèques d'API alternatives si nécessaire.

Voici mon 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
Je dépend de la bibliothèque de gestion d'état que vous utilisez. Si vous n'en utilisez pas, vous pouvez déplacer vos appels API vers le fichier séparé et appeler les fonctions API dans votre situation en componentDidMountcallback.
1ven

Vous pouvez utiliser à la fetch()place de jQuery si vous utilisez uniquement jQuery pour faire des requêtes Ajax.
Fred

Pourquoi utiliser Jquery? Jquery est une énorme bibliothèque et ce n'est pas nécessaire
Robin

Il suffit d'ajouter ici que useEffectc'est probablement l'endroit où passer des appels API maintenant. Voir btholt.github.io/complete-intro-to-react-v5/effects
shw

Réponses:


98

Dans ce cas, vous pouvez faire un appel ajax à l'intérieur componentDidMount, puis mettre à jourstate

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
Cela a fonctionné, merci .. Pourriez-vous s'il vous plaît me suggérer "laquelle est la meilleure bibliothèque pour une meilleure gestion de l'état"
Raj Rj

3
@Raj Rj ces jours-ci, je pense que c'est Redux
Alexander T.3

8
Redux est plus populaire de nos jours, son style provient d'une programmation fonctionnelle. Si vous venez du style POO, Mobx ( mobxjs.github.io/mobx ) est une excellente bibliothèque de gestion d'état, elle vous permet de vous concentrer sur l'écriture de code d'entreprise et de réduire finalement votre code standard
Nhan Tran

25

Vous voudrez peut-être consulter l' Architecture Flux . Je recommande également de vérifier l' implémentation React-Redux . Mettez vos appels API dans vos actions. C'est beaucoup plus propre que de tout mettre dans le composant.

Les actions sont des sortes de méthodes d'assistance que vous pouvez appeler pour modifier l'état de votre application ou effectuer des appels API.


Troper Merci. Alors, dois-je conserver mes appels liés à l'API dans des fichiers séparés? Et comment les appeler dans ma "classe de composants"? Quelle structure de dossier dois-je suivre? Quelle est la meilleure pratique? PS- Je suis nouveau pour réagir en posant ces questions de base.
Raj Rj

Dans l'implémentation redux, les méthodes d'action sont injectées aux composants. Ces méthodes deviendront désormais des accessoires de votre composant que vous pouvez appeler. Vous pouvez consulter react-redux-starter-kit pour la structure.
Jei Trooper

12

Utilisez la fetchméthode à l'intérieur componentDidMountpour mettre à jour l'état:

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

11

Cette discussion dure depuis un certain temps et la réponse de @Alexander T. a fourni un bon guide à suivre pour les plus récents de React comme moi. Et je vais partager des connaissances supplémentaires sur l'appel à plusieurs reprises de la même API pour actualiser le composant, je pense que c'est probablement un problème courant auquel les débutants peuvent être confrontés au début.

componentWillReceiveProps(nextProps), à partir de la documentation officielle :

Si vous devez mettre à jour l'état en réponse aux changements de prop (par exemple, pour le réinitialiser), vous pouvez comparer this.props et nextProps et effectuer des transitions d'état en utilisant this.setState () dans cette méthode.

Nous pourrions en conclure que c'est ici que nous gérons les accessoires du composant parent, que nous avons des appels d'API et que nous mettons à jour l'état.

Basé sur l'exemple de @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 (...)
  }
}

Mettre à jour

componentWillReceiveProps() serait obsolète.

Voici seulement quelques méthodes (toutes dans Doc ) dans le cycle de vie qui, je pense, seraient liées au déploiement de l'API dans le cas général: entrez la description de l'image ici

En vous référant au schéma ci-dessus:

  • Déployer l'API dans componentDidMount()

    Le scénario approprié pour avoir un appel d'API ici est que le contenu (de la réponse de l'API) de ce composant sera statique, componentDidMount()ne se déclenche qu'une seule fois pendant le montage du composant, même les nouveaux accessoires sont passés du composant parent ou ont des actions à diriger re-rendering.
    Le composant vérifie la différence pour re-rendre mais pas re-monter .
    Citation du doc :

Si vous devez charger des données à partir d'un point de terminaison distant, c'est un bon endroit pour instancier la demande réseau.


  • Déployer l'API dans static getDerivedStateFromProps(nextProps, prevState)

Nous devrions remarquer qu'il ya deux types de mise à jour le composant , setState() dans le composant actuel ne pas conduire cette méthode pour déclencher, mais les accessoires re-rendu ou nouveaux de composant parent entreprenons . Nous avons pu découvrir que cette méthode se déclenche également lors du montage.

C'est un endroit approprié pour déployer l'API si nous voulons utiliser le composant actuel comme un modèle, et les nouveaux paramètres pour l'API sont des accessoires provenant du composant parent .
Nous recevons une réponse différente de l'API et renvoyons une nouvelle stateici pour modifier le contenu de ce composant.

Par exemple:
Nous avons une liste déroulante pour différentes voitures dans le composant parent, ce composant doit afficher les détails de celui sélectionné.


  • Déployer l'API dans componentDidUpdate(prevProps, prevState)

À la différence de static getDerivedStateFromProps(), cette méthode est appelée immédiatement après chaque rendu sauf le rendu initial. Nous pourrions avoir un appel d'API et rendre la différence dans un composant.

Prolongez l'exemple précédent:
le composant pour afficher les détails de la voiture peut contenir une liste de séries de cette voiture, si nous voulons vérifier la production de 2013, nous pouvons cliquer ou sélectionner ou ... l'élément de liste pour diriger une première setState()pour refléter cela comportement (comme la mise en évidence de l'élément de liste) dans ce composant, et dans ce qui suit, componentDidUpdate()nous envoyons notre demande avec de nouveaux paramètres (état). Après avoir obtenu la réponse, nous avons à setState()nouveau rendu le contenu différent des détails de la voiture. Pour éviter que ce qui suit componentDidUpdate()ne provoque la boucle à l'infini, nous devons comparer l'état en utilisant prevStateau début de cette méthode pour décider si nous envoyons l'API et rendons le nouveau contenu.

Cette méthode pourrait vraiment être utilisée comme static getDerivedStateFromProps()avec les accessoires, mais doit gérer les changements de propsen utilisant prevProps. Et nous devons coopérer avec componentDidMount()pour gérer l'appel d'API initial.

Citation du doc :

... C'est aussi un bon endroit pour faire des requêtes réseau tant que vous comparez les accessoires actuels aux accessoires précédents ...


10

Je voudrais que vous jetiez un œil à redux http://redux.js.org/index.html

Ils ont une manière très bien définie de gérer les appels asynchrones, c'est-à-dire les appels d'API, et au lieu d'utiliser jQuery pour les appels d'API, je voudrais recommander d'utiliser fetch ou request npm packages, fetch est actuellement pris en charge par les navigateurs modernes, mais un shim est également disponible pour du côté serveur.

Il y a aussi un autre superagent de package étonnant , qui a beaucoup d'options lors de la demande d'API et est très facile à utiliser.


3

La fonction de rendu doit être pure, cela signifie qu'elle n'utilise que l'état et les accessoires pour le rendu, n'essayez jamais de modifier l'état dans le rendu, cela provoque généralement de vilains bogues et diminue considérablement les performances. C'est également un bon point si vous séparez les problèmes de récupération de données et de rendu dans votre application React. Je vous recommande de lire cet article qui explique très bien cette idée. https://medium.com/@learnreact/container-components-c0e67432e005#.sfydn87nm


3

Cette partie de la documentation React v16 répondra à votre question, lisez la suite à propos de componentDidMount ():

componentDidMount ()

componentDidMount () est appelé immédiatement après le montage d'un composant. L'initialisation qui nécessite des nœuds DOM doit aller ici. Si vous devez charger des données à partir d'un point de terminaison distant, c'est un bon endroit pour instancier la demande réseau. Cette méthode est un bon endroit pour configurer des abonnements. Si vous faites cela, n'oubliez pas de vous désabonner dans componentWillUnmount ().

Comme vous le voyez, componentDidMount est considéré comme le meilleur endroit et le meilleur cycle pour faire l' appel api , accéder également au nœud, ce qui signifie qu'à ce moment-là, il est sûr de faire l'appel, de mettre à jour la vue ou tout ce que vous pourriez faire lorsque le document est prêt, si vous êtes en utilisant jQuery, cela devrait en quelque sorte vous rappeler la fonction document.ready (), où vous pouvez vous assurer que tout est prêt pour tout ce que vous voulez faire dans votre code ...


3

1) Vous pouvez utiliser F etch API pour récupérer des données à partir de Endd Points:

Exemple de récupération de tout Githubrepos pour un utilisateur

  /* 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) Une autre alternative est Axios

En utilisant axios, vous pouvez couper l'étape intermédiaire de la transmission des résultats de la requête http à la méthode .json (). Axios renvoie simplement l'objet de données auquel vous vous attendez.

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

Vous pouvez désormais choisir d'extraire des données à l'aide de l'une de ces stratégies dans componentDidMount

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

  componentDidMount() {
    this.fetchData ();
  }

En attendant, vous pouvez afficher la barre de progression pendant le chargement des données

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

2

Vous pouvez également récupérer des données avec des hooks dans vos composants de fonction

exemple complet avec appel api: https://codesandbox.io/s/jvvkoo8pq3

deuxième exemple: 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

Comme meilleur endroit et pratique pour les appels API externes est React méthode du cycle de vie componentDidMount () , où après l'exécution de l'appel de l' API , vous devez mettre à jour l'état local à déclencher une nouvelle render () appel de méthode, les modifications de l'état local mis à jour sera être appliqué sur la vue du composant.

Comme autre option pour l' appel initial de la source de données externe dans React est pointée la méthode constructor () de la classe. Le constructeur est la première méthode exécutée lors de l'initialisation de l'instance d'objet composant. Vous pouvez voir cette approche dans les exemples de documentation pour les composants d'ordre supérieur .

Les méthodes componentWillMount () et UNSAFE_componentWillMount () ne doivent pas être utilisées pour les appels d'API externes, car elles sont destinées à être obsolètes. Ici, vous pouvez voir les raisons courantes pour lesquelles cette méthode sera obsolète.

Quoi qu'il en soit, vous ne devez jamais utiliser la méthode render () ou la méthode directement appelée depuis render () comme point d'appel d'API externe. Si vous faites cela, votre application sera bloquée .


0

Une méthode simple consiste à effectuer un appel d'API asynchrone dans componentDidMount avec la fonction try / catch .

Lorsque nous appelons une API, nous recevons une réponse. Ensuite, nous appliquons la méthode JSON dessus, pour convertir la réponse en un objet JavaScript. Ensuite, nous prenons de cet objet de réponse uniquement son objet enfant nommé "results" (data.results).

Au début, nous avons défini "userList" dans l'état comme un tableau vide. Dès que nous effectuons l'appel d'API et recevons des données de cette API, nous attribuons les "résultats" à userList à l'aide de la méthode setState .

À l'intérieur de la fonction de rendu, nous disons que userList proviendra de l'état. Puisque la userList est un tableau d'objets que nous mappons à travers elle, pour afficher une image, un nom et un numéro de téléphone de chaque objet "utilisateur". Pour récupérer ces informations, nous utilisons la notation par points (par exemple, user.phone).

REMARQUE : selon votre API, votre réponse peut être différente. Console.log la "réponse" entière pour voir les variables dont vous avez besoin, puis les affecter dans setState.

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

Ce serait génial d'utiliser axios pour la demande d'API qui prend en charge l'annulation, les intercepteurs, etc. Avec axios, j'utilise react-redux pour la gestion des états et redux-saga / redux-thunk pour les effets secondaires.


Bien que ce ne soit pas incorrect, car l'utilisation d'axios et de redux est un moyen valide de récupérer des données et de gérer l'état, cela ne répond pas vraiment à la question et c'est plus proche d'un commentaire.
Emile Bergeron
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.