use - Cette fonctionnalité est disponible dans le dernier Canary

Canary (fonctionnalité expérimentale)

Le Hook use n’est actuellement disponible que sur les canaux de livraison Canary et Expérimental de React. Apprenez-en davantage sur les canaux de livraison React.

use est un Hook React qui vous permet de lire la valeur d’une ressource telle qu’une promesse ou un contexte.

const value = use(resource);

Référence

use(resource)

Appelez use dans votre composant pour lire la valeur d’une ressource telle qu’une promesse ou un contexte.

import { use } from 'react';

function MessageComponent({ messagePromise }) {
const message = use(messagePromise);
const theme = use(ThemeContext);
// ...

Contrairement à tous les autres Hooks React, use peut être appelé au sein de boucles ou d’instructions conditionnelles telles que if. En revanche, comme pour les autres Hooks React, toute fonction appelant use doit être un composant ou un Hook.

Lorsqu’il est appelé avec une promesse, le Hook use s’intègre avec Suspense et les périmètres d’erreurs. Le composant appelant suspend tant que la promesse passée à use est en attente. Si le composant qui appelle use est enrobé dans un périmètre Suspense, l’UI de secours est affichée. Une fois la promesse accomplie, cette UI est remplacée par le rendu des composants en utilisant les données renvoyées par le Hook use. Si la promesse renvoyée par use est rejetée, l’UI de secours du périmètre d’erreur le plus proche est affichée.

Voir d’autres exemples plus bas.

Paramètres

  • resource : c’est la source de données depuis laquelle vous voulez lire une valeur. Une ressource peut être une promesse ou un contexte.

Valeur renvoyée

Le Hook use renvoie la valeur lue depuis la ressource, telle que la valeur accomplie d’une promesse ou la valeur actuelle d’un contexte.

Limitations

  • Le Hook use doit être appelé à l’intérieur d’un composant ou d’un Hook.
  • Lorsque vous récupérez des données dans un Composant Serveur, privilégiez async et await plutôt que use. async et await reprennent le rendu à partir du point où await avait été invoqué, alors que use refait un rendu du composant une fois la donnée obtenue.
  • Privilégiez la création de promesses dans les Composants Serveur et leur passage aux Composants Client, plutôt que de créer des promesses dans les Composants Client. Les promesses créées dans les Composants Client sont recréées à chaque rendu. Les promesses transmises d’un Composant Serveur à un Component Client ne changent pas d’un rendu à l’autre. Consultez cet exemple.

Utilisation

Lire un contexte avec use

Quand un contexte est passé à use, ce dernier fonctionne de la même façon que useContext. Alors que useContext doit être appelé à la racine de votre composant, use peut être appelé à l’intérieur de conditions telles que if ou de boucles telles que for. use est préférable à useContext parce qu’il est plus flexible.

import { use } from 'react';

function Button() {
const theme = use(ThemeContext);
// ...

use renvoie la valeur de contexte pour le contexte que vous avez transmis. Pour déterminer la valeur du contexte, React remonte l’arbre des composants pour trouver le fournisseur de contexte parent le plus proche pour ce contexte.

Pour transmettre un contexte à un Button, enrobez ce bouton ou l’un de ses parents dans le fournisseur de contexte adéquat.

function MyPage() {
return (
<ThemeContext.Provider value="dark">
<Form />
</ThemeContext.Provider>
);
}

function Form() {
// ... rendu des boutons ici ...
}

Peu importe le nombre de couches de composants qu’il y a entre le fournisseur et le Button. Quand un Button appelle use(ThemeContext), il recevra la valeur "dark", quelle que soit sa position au sein du Form.

Contrairement à useContext, use peut être appelé dans les blocs conditionnels et les boucles, comme par exemple un if.

function HorizontalRule({ show }) {
if (show) {
const theme = use(ThemeContext);
return <hr className={theme} />;
}
return false;
}

use est appelé à l’intérieur d’une instruction if, ce qui vous permet de ne lire des valeurs de contextes que sous certaines conditions.

Piège

Tout comme useContext, use(context) cherche toujours le fournisseur de contexte le plus proche au-dessus du composant qui l’appelle. Il remonte et ignore les fournisseurs de contexte situés dans le composant depuis lequel vous appelez use(context).

import { createContext, use } from 'react';

const ThemeContext = createContext(null);

export default function MyApp() {
  return (
    <ThemeContext.Provider value="dark">
      <Form />
    </ThemeContext.Provider>
  )
}

function Form() {
  return (
    <Panel title="Bienvenue">
      <Button show={true}>Inscription</Button>
      <Button show={false}>Connexion</Button>
    </Panel>
  );
}

function Panel({ title, children }) {
  const theme = use(ThemeContext);
  const className = 'panel-' + theme;
  return (
    <section className={className}>
      <h1>{title}</h1>
      {children}
    </section>
  )
}

function Button({ show, children }) {
  if (show) {
    const theme = use(ThemeContext);
    const className = 'button-' + theme;
    return (
      <button className={className}>
        {children}
      </button>
    );
  }
  return false
}

Diffuser en continu des données du serveur au client

Les données peuvent être transmises en continu du serveur au client en passant une promesse comme prop depuis un Composant Serveur vers un Composant Client.

import { fetchMessage } from './lib.js';
import { Message } from './message.js';

export default function App() {
const messagePromise = fetchMessage();
return (
<Suspense fallback={<p>En attente d’un message...</p>}>
<Message messagePromise={messagePromise} />
</Suspense>
);
}

Le Composant Client prend ensuite la promesse qu’il a reçue comme prop et la transmet au Hook use. Ça permet au Composant Client de lire la valeur de la promesse initialement créée par le Composant Serveur.

// message.js
'use client';

import { use } from 'react';

export function Message({ messagePromise }) {
const messageContent = use(messagePromise);
return <p>Voici le message : {messageContent}</p>;
}

Puisque Message est enrobé dans un Suspense, l’UI de secours sera affichée en attendant l’accomplissement de la promesse. Lorsqu’elle s’accomplit, la valeur sera lue par le Hook use et le composant Message remplacera l’UI de secours de Suspense.

"use client";

import { use, Suspense } from "react";

function Message({ messagePromise }) {
  const messageContent = use(messagePromise);
  return <p>Voici le message : {messageContent}</p>;
}

export function MessageContainer({ messagePromise }) {
  return (
    <Suspense fallback={<p>⌛ Téléchargement du message...</p>}>
      <Message messagePromise={messagePromise} />
    </Suspense>
  );
}

Remarque

Lorsque vous transmettez une promesse d’un Composant Serveur à un Composant Client, sa valeur accomplie doit être sérialisable pour pouvoir être communiquée entre le serveur et le client. Les types de données comme les fonctions ne sont pas sérialisables et ne peuvent donc pas être utilisés comme valeur accomplie d’une telle promesse.

En détail

Dois-je accomplir une promesse dans un Composant Serveur ou Client ?

Une promesse peut être passée d’un Composant Serveur à un Composant Client, puis accomplie dans le Composant Client avec le Hook use. Vous pouvez également accomplir la promesse dans un Composant Serveur avec await, puis transmettre les données requises au Composant Client en tant que prop.

export default async function App() {
const messageContent = await fetchMessage();
return <Message messageContent={messageContent} />
}

Toutefois, l’utilisation d’await dans un Composant Serveur bloquera son rendu jusqu’à ce que l’instruction await ait terminé. Le passage d’une promesse d’un Composant Serveur à un Composant Client permet à la promesse de ne pas bloquer le rendu du Composant Serveur.

Traiter les promesses rejetées

Dans certains cas, une promesse passée à use peut être rejetée. Vous pouvez gérer les promesses rejetées en utilisant l’une ou l’autre de ces méthodes :

  1. afficher une erreur aux utilisateurs avec un périmètre d’erreur
  2. fournir une valeur alternative avec Promise.catch

Piège

use ne peut pas être appelé à l’intérieur d’un bloc try-catch. En remplacement de ces blocs, enrobez votre composant dans un périmètre d’erreur, ou fournissez une valeur alternative à utiliser avec la méthode .catch des promesses.

Afficher une erreur aux utilisateurs avec un périmètre d’erreur

Si vous souhaitez afficher une erreur à vos utilisateurs quand une promesse a été rejetée, vous pouvez utiliser un périmètre d’erreur. Pour l’utiliser, enrobez le composant d’où vous appelez le Hook use dans le périmètre d’erreur. Si la promesse transmise à use est rejetée, alors l’UI de secours de ce périmètre d’erreur sera affichée.

"use client";

import { use, Suspense } from "react";
import { ErrorBoundary } from "react-error-boundary";

export function MessageContainer({ messagePromise }) {
  return (
    <ErrorBoundary fallback={<p>⚠️ Ça sent le pâté…</p>}>
      <Suspense fallback={<p>⌛ Téléchargement du message...</p>}>
        <Message messagePromise={messagePromise} />
      </Suspense>
    </ErrorBoundary>
  );
}

function Message({ messagePromise }) {
  const content = use(messagePromise);
  return <p>Voici le message : {content}</p>;
}

Fournir une valeur alternative avec Promise.catch

Si vous voulez fournir une valeur alternative quand la promesse passée à use est rejetée, vous pouvez utiliser la méthode catch des promesses.

import { Message } from './message.js';

export default function App() {
const messagePromise = new Promise((resolve, reject) => {
reject();
}).catch(() => {
return "Aucun nouveau message.";
});

return (
<Suspense fallback={<p>En attente de message...</p>}>
<Message messagePromise={messagePromise} />
</Suspense>
);
}

Pour utiliser la méthode catch de la promesse, appelez catch sur l’objet Promise. catch n’accepte qu’un seul paramètre : une fonction qui prend une erreur comme argument. La valeur de retour de la fonction passée à catch sera utilisée comme valeur accomplie de la promesse.


Dépannage

“Suspense Exception: This is not a real error!”

(« Exception Suspense : ce n’est pas une véritable erreur ! », NdT)

Vous appelez probablement use soit en-dehors d’un composant React ou d’une fonction de Hook, soit dans un bloc try-catch. Pour corriger ce dernier cas, enrobez votre composant dans un périmètre d’erreur ou appelez la fonction catch de la promesse pour attraper l’erreur et résoudre la promesse avec une valeur différente. Consultez ces exemples.

Si vous appelez use en-dehors d’un composant React ou d’une fonction de Hook, déplacez l’appel à use dans un composant React ou une fonction de Hook.

function MessageComponent({messagePromise}) {
function download() {
// ❌ la fonction appelant `use` n'est ni un composant ni un Hook
const message = use(messagePromise);
// ...

Appelez plutôt use hors de toute fermeture lexicale au sein du composant, lorsque la fonction qui appelle use est un composant ou un Hook.

function MessageComponent({messagePromise}) {
// ✅ `use` est appelé depuis un composant
const message = use(messagePromise);
// ...