Appeler une API dans un composant fonctionnel React

Sous React il est possible d’écrire un composant Web de deux manières : soit via une fonction, soit via une classe. Mais il n’était pas possible de gérer des variables d’états depuis un composant fonctionnel et encore moins les méthodes de cycle de vie proposées par les composants de classe. React a introduit depuis la version 16.8 de leur librairie la notion de Hooks qui permet de bénéficier des fonctionnalités présentes dans les composants de classes depuis les composants fonctionnels.

Il devient alors possible de développer un site Web uniquement avec des composants fonctionnels. Pourquoi ? me direz-vous. Les équipes React expliquent les motivations qui ont amené ce choix technique, mais pour résumer, un composant fonctionnel est tout simplement plus court et facile à lire, améliorant la maintenance et la compréhension du code. Il n’y a plus d’utilisation du mot clé this ainsi que les lignes nécessaire à la construction du composant : le constructeur, le binding des fonctions.

useState et useEffect

Si vous avez déjà développé une application avec la librairie React en passant par des composants de classes, vous savez que l’état de vos variables se gère à l’aide de la méthode setState, héritée de React.Component, et qu’il est de mise de positionner les appels aux API dans la méthode de cycle de vie componentdidMount. Les Hooks useState et useEffect permettent de reproduire ce schéma dans un composant fonctionnel.

Le hook useState permet de gérer l’état d’une variable et s’utilise de cette manière dans un composant fonctionnel :

import react, { useState } from "react";

const FunctionalComponent = () => {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Click</button>
    </div>
  );
};

export default FunctionalComponent;

L’équivalent pour un composant de classe reviendrait à ça :

import react from "react";

export class ClassComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0,
    };
  }

  render() {
    return (
      <div>
        <p>count: {this.state.count} times</p>
        <button onClick={() => this.setState({ count: this.state.count + 1 })}>
          Click
        </button>
      </div>
    );
  }
}

Le hook useEffect permet de reproduire l’utilisation des méthodes componentDidMount, componentDidUpdate et componentWillUnmount dans un même endroit. Si vous aviez à écrire un composant de classe utilisant des méthodes de cycle de vie ça pourrait ressembler à ça :

import react from "react";

export class ClassComponent extends React.Component {
  componentDidMount() {
    console.log("Enter component.");
  }

  componantWillUnmount() {
    console.log("Leave component.");
  }

  render() {
    return <h1>Hello World !</h1>;
  }
}

L’équivalent avec l’utilisation du hook useEffect dans un composant fonctionnel :

import react, { useEffect } from "react";

const FunctionalComponent = () => {
  useEffect(() => {
    console.log("Enter component.");
    return () => {
      console.log("Leave component");
    };
  }, []);
  return <h1>Hello World !</h1>;
};

export default FunctionalComponent;

A chaque changement d’état et de rendu, useEffect sera appelé par React. L’élément important est le deuxième paramètre du hook qui prends en argument un tableau de variables (dans notre exemple le tableau est vide). Si une variable gérée par le hook useState est déclarée dans ce tableau alors l’effet ne s’exécutera que si la variable change d’état.

Appeler une API

Maintenant que vous avez ces deux notions en tête nous allons pouvoir écrire un composant fonctionnel qui appelle une API pour récupérer et restituer des données. Première chose à faire rédiger un service chargé de contacter l’API et proposant des méthodes de restitution des données :

function api() {
  const getUsers = () => {
    return fetch("http://localhost:8000/api/users", {
      type: "GET",
    }).then((res) => res.json());
  };

  return {
    getUsers,
  };
}

export default api();

L’exemple est délibérément simple pour illustrer la démonstration. Maintenant place au code du composant fonctionnel :

import React, { useState, useEffect } from "react";
import api from "./api";

const UserList = () => {
  const [users, setUsers] = useState([]);
  const [isMounted, setIsMounted] = useState(false);

  useEffect(() => {
    !isMounted &&
      api.getUsers().then((json) => {
        setUsers(json);
        setIsMounted(true);
      });
  }, [isMounted]);

  return (
    <ul>
      {users && users.map((user, index) => {
          return (
            <li key={index}>
              {user.Nom} {user.Prenom}
            </li>
          );
        })}
    </ul>
  );
};

export default UserList;

Le hook useState permet de gérer l’état de notre liste d’utilisateurs ainsi que la variable isMounted qui s’assure que notre API ne soit appelée qu’une seule fois lors du chargement du composant.

L’appel à notre API se fait au niveau du hook useEffect. La variable isMounted est déclarée dans le tableau en deuxième paramètre du hook, indiquant que l’effet ne s’effectue que si un changement d’état s’opère.

Conclusion

Vous avez vu dans cette article à quoi servent et comment s’utilisent les hooks useState et useEffect amenés par la version 16.8 de React. Vous avez également pu appliquer ces concepts pour appeler et consommer une API dans un composant fonctionnel React.

Grâce aux hooks, l’écriture d’un composant devient plus simple et lisible. Il est possible d’arriver au même résultat qu’un composant de classe mais en écrivant beaucoup moins de lignes de code.

Références

One Reply to “Appeler une API dans un composant fonctionnel React”

  1. Si vous avez la flemme de développer une API qui écoute sur le port 8000 pour tester ce code, vous pouvez toujours remplacer le contenu de getUsers avec le code suivant :

    const getUsers = async () => {
      return [
        {Nom: 'Perrot', Prenom: 'Cyrille'},
        {Nom: 'Martin', Prenom: 'Pierre'},
        {Nom: 'Dupont', Prenom: 'Jean'}
      ];
    };
    

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.

Appeler une API dans un composant fonctionnel React

par Cyrille Perrot Temps de lecture: 4 min
1