👾 À première vu on pourrait être tenté de faire quelque chose de la sorte pour récupérer le contenu d'une API distante.

const MyFunctionnalComponent: React.FC = (props) => {
  useEffect(async () => {
   await loadContent();
  }, []);
  
  return <div></div>;
}

🤔 Qu'est-ce qui ne va pas avec ce morceau de code ?

Si on utilise Typescript, le compilateur doit nous sortir une erreur de la sorte :

Argument of type '() => Promise<void>' is not assignable to parameter of type 'EffectCallback'.

Regardons la signification de cette erreur en lisant la définition d'une fonction asynchrone :

Une fonction qui permet d'utiliser des instructions asynchrone avec le mot clé await, ce qui bloquera l'execution du code tant que la Promesse après laquelle le mot clé await se trouve n'aura pas résolu…

Ok… Ça me semble bien mais… voyons la suite…

Cette fonction va également retourner une Promesse, peu importe si l'on a explicitement retourné quelque chose ou non. Dans le cas où l'on retourne une donnée, elle sera enveloppée dans le contenu de resolution de la Promese que la fonction va créer et retourner automatiquement.

Ouch! Vous commencez à voir le problème ? Non ? Allons voir la définition du hook  useEffect ici : https://fr.reactjs.org/docs/hooks-reference.html#useeffect

Souvent, les effets de bord créent des ressources qui nécessitent d’être  nettoyées avant que le composant ne quitte l’écran, telles qu’un  abonnement ou l’ID d’une horloge. Pour ce faire, la fonction fournie à useEffect peut renvoyer une fonction de nettoyage. Par exemple, pour créer un abonnement.

📌 Utiliser une async fonction fait retourner à la fonction de retour une Promesse au lieu d'une fonction de nettoyage.

Et c'est la raison pour laquelle le compilateur nous crie dessus en Typescript. Ce pattern est également vrai pour du Javascript sans Typescript car React n'attends pas une Promesse mais une fonction.

💡Comment traiter le code asynchrone dans useEffect ?

En utilisant la technique suivante, nous serons capables d'utiliser la fonction asynchrone dans nos effets :

const MyFunctionnalComponent: React.FC = props => {
  useEffect(() => {
    // Create an scoped async function in the hook
    async function anyNameFunction() {
      await loadContent();
    }    // Execute the created function directly
    anyNameFunction();
  }, []);
  
  return <div></div>;
};

Maintenant, votre code est sécurisé car vous ne renvoyez rien du tout et le compilateur a cessé de crier.

Vous pouvez également utiliser un IIFE, qui a le même effet que ci-dessus.

const MyFunctionnalComponent: React.FC = props => {
  useEffect(() => {
    // Using an IIFE
    (async function anyNameFunction() {
      await loadContent();
    })();
  }, []);  
  
  return <div></div>;
};