useThis feature is available in the latest Canary

Canari (fonctionnalité expérimentale)

Le Hook use n’est actuellement disponible que sur les canaux de distribution canari et expérimentaux de React. Apprenez-en davantage sur les canaux de versions de React ici.

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 aux autres Hooks React, use peut être appelé au sein des boucles ou des instructions conditionnelles comme le if. La fonction qui appelle use doit cependant être un composant ou un Hook, comme les autres Hooks React.

Lorsqu’il est appelé avec une promesse, le Hook use s’intègre au Suspense et au périmètre d’erreur. Le composant appelant est suspendu tant que la promesse passée à use est en attente. Si le composant qui appelle use est enrobé dans un périmètre de Suspense, l’UI de secours sera affichée. Une fois la promesse résolue, cette UI est remplacée par le rendu des composants qui utilisent les données renvoyées par le Hook use. Si cette promesse 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 le source de données dont vous voulez lire une valeur. Une ressource peut être une promesse ou un contexte.

Valeur renvoyée

Le Hook use renvoie la valeur qui a été lue depuis la ressource, telle que la valeur résolue d’une promesse ou 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 résolue.
  • Privilégiez la création de promesses pour les composants serveur, et passez-les 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 lors de chaque rendu. Les promesses transmises d’un composant serveur à un component client ne changent pas entre les rendus. Consultez cet exemple.

Utilisation

Lire le 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 comme if ou des boucles comme 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 cherche dans l’arbre des composants 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() {
// ... faire le 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", quelque soit sa position dans Form.

Contrairement à useContext, use peut être appelé dans les blocs conditionnels et les boucles comme le 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 lire des valeurs d’un contexte dans 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 cherche en remontant 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}>S'enregister</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 à 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çu comme prop et la transmet au Hook use. Ça permet au composant client de lire la valeur de la promesse qui a été créée initialement 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>;
}

Parce que Message est enrobé dans un Suspense, l’UI de secours sera affichée en attendant la résolution de la promesse. Lorsqu’elle est résolue, la valeur sera lue par le Hook use et le composant Message remplacera l’UI de secours du 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 de résolution 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 de résolution d’une telle promesse.

En détail

Dois-je résoudre une promesse sur le composant serveur ou client ?

Une promesse peut être passée d’un composant serveur à un composant client, puis résolue dans le composant client avec le Hook use. Vous pouvez également résoudre la promesse dans un composant serveur avec await, puis transmettre les données requises au composant client en tant que prop.

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

Toutefois, l’utilisation du await dans un composant serveur bloquera le rendu jusqu’à ce que l’instruction await soit terminée. 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. À la place de ce type de bloc, 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 dans 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 est affichée.

"use client";

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

export function MessageContainer({ messagePromise }) {
  return (
    <ErrorBoundary fallback={<p>⚠️ Quelque chose s'est mal passé</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 un message d’erreur comme argument. Ce qui est renvoyé par la fonction passée à catch sera utilisé comme valeur résolue de la promesse.


Dépannage

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

Vous appelez use soit en dehors d’un composant React soit d’une fonction de Hook, ou encore vous appelez use dans un bloc try-catch. Pour résoudre ce dernier cas, enrobez votre composant dans un périmètre d’erreur ou appelez la fonction Promise.catch 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 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 en dehors de toute fermeture lexicale des composants, 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);
// ...