AccueilClientsExpertisesBlogOpen SourceContact

24 mars 2025

Comment fonctionne l’API use avec Next 15 et React 19 ?

8 minutes de lecture

Comment fonctionne l’API use avec Next 15 et React 19 ?
🇺🇸 This post is also available in english

Le data fetching et les mutations sont les pierres angulaires de nombreux sites web. Pour les développeurs frontend, l'objectif est souvent de mettre en place des interfaces performantes tout en garantissant une expérience utilisateur fluide. Mais alors que les solutions sont de plus en plus nombreuses pour la gestion des données, comment choisir la bonne ?

Dans cet article, nous allons nous intéresser aux différentes solutions disponibles avec Next 15 et React 19. Ce sera l'occasion de découvrir quelques nouvelles fonctionnalités de React 19 comme l'API use nouvellement introduite, maintenant stable depuis quelques mois.

Quelques rappels

Ici, nous allons beaucoup parler des Client Components, Server Components, Server Actions et de la manière dont l'ensemble s'articule pour servir et manipuler les données. Si vous n'êtes pas familier avec ces concepts, je vous invite à lire les articles Next 13.4 : Tour d'horizon des server actions et Focus sur le nouveau routeur app de Next 13. On notera que le volet sur les mutations de données n'a pas beaucoup évolué depuis la version 13, nous nous concentrerons donc sur la partie relative au data fetching.

Concepts-clés

Jusqu'à la version 15, il existait quatre manières de récupérer des données :

Client Components

  • fetch: Récupérer des données directement côté client

Cette approche se fait en passant souvent par une librairie tierce comme React Query ou dans un hook useEffect doublé d'une gestion d'état. Cela permet de récupérer des données directement côté client sans passer par le serveur. Cependant, cette méthode souffre de quelques limitations, notamment en termes de performances car les données ne seront récupérées que lorsque le composant sera monté, ce qui peut donner une impression de latence à l'utilisateur.

Pour rappel l'API fetch est surchargée par NextJS et dispose de fonctionnalités supplémentaires par rapport à l'API fetch native, comme la gestion du cache et de la revalidation des données.

  • server actions: Appelées depuis le client, exécutées sur le serveur

Sensiblement identique à un fetch côté client, cette méthode offre une developer experience plus simple. Mais souffre des mêmes limitations que le fetch côté client. S'ajoute à cela le fait que les server actions peuvent ouvrir la porte à des erreurs de sécurité si on se laisse bercer par leur implémentation facile et que l'on oublie de sécuriser ces fonctions - pour rappel, ce sont des endpoints crées automatiquement, c'est pour cette raison qu'il faut les protéger.

L'usage de server actions ou de l'API fetch sera déterminé par le contexte de l'application, si vous exploitez une API externe, vous aurez besoin d'utiliser l'API fetch côté client, au contraire si vous avez un ORM comme Prisma ou Drizzle, vous pourrez utiliser les server actions qui pourront utiliser vos fonctions de manipulation de données.

Server Components

  • fetch: Récupération de données sur le serveur puis passage à l'UI
  • server function: Exécutées sur le serveur puis passage à l'UI

☝️ Ici on précise que ce sont des server functions car elles ne sont pas nécessairement des server actions (sans la directive use server), ce qui évite la création d'un endpoint qui serait non exploité par un Client Component.

Dans les deux cas, on parle de fonctions asynchrones, qui seront attendues par le serveur avant de passer à l'UI. Le rendu de la page sera donc bloqué tant que la fonction ne sera pas terminée.

Bilan des méthodes classiques

En fonction du besoin, on peut avoir besoin de récupérer des données côté client ou côté serveur. Dans le cas où le data fetching implique une interaction utilisateur préalable, il faudra utiliser un Client Component et donc un fetch ou une server action, avec les limitations que cela implique sur les performances. Si aucune interaction utilisateur n'est nécessaire, on peut utiliser un Server Component et donc une server function ou un fetch côté serveur, avec l'inconvénient de bloquer le rendu de la page tant que les données ne sont pas récupérées.

Pour la partie récupération de données dynamiques, peu de choses ont changé depuis la version 13. Cependant, pour la partie récupération de données statiques, on a désormais une plus grande marge de manœuvre, principalement autour de l'expérience utilisateur, c'est ce que nous allons voir avec l'utilisation de l'API use.

L'API use et le passage de Promises

On vient de le voir, la récupération de données côté serveur comporte des limitations. Notamment en termes de performances, principalement due au fait que le rendu de la page est bloqué tant que les données ne sont pas récupérées car ces données sont récupérées de manière synchrone (utilisation du await). Ce qui peut être problématique avec une grande quantité de données ou une latence importante.

Depuis l'apparition des Server Components, il est possible de passer des Promises à un Client Composant, du moment où le résultat de la Promise est une valeur sérialisable (pas de fonction donc). Cependant, jusqu'à présent, il n'était pas possible de bloquer le rendu du Client Component tant que la Promise n'est pas résolue.

Pour répondre à ce problème, React 19 introduit une nouvelle API: use. Nous allons voir comment cette nouvelle API permet de cibler le composant qui doit attendre la résolution de la Promise, et d'afficher un fallback jusqu'à ce que la Promise soit résolue, voire une erreur si la Promise est rejetée.

Optimiser l'expérience utilisateur

Comment fonctionne le passage de Promises avec Next ?

Pour bien comprendre le fonctionnement de l'API use, intéressons-nous à la manière dont Next 15 gère le passage de Promises à un Client Component. Pour l'exemple, nous allons récupérer les données de l'ensemble des planètes du système solaire.

app/planets/page.tsx
import { getPlanets, type Planet } from '@/lib/planets'
import Planets from './Planets'

export default function PlanetsPage() {
  const planetsPromise: Promise<Planet[]> = getPlanets() // Récupération asynchrone des données

  return <Planets planetsPromise={planetsPromise} />
}

Dans cet exemple, lorsque l'utilisateur navigue vers la page /planets, le serveur Next va :

  1. Faire un rendu de la page, non bloqué car la Promise est envoyée de manière asynchrone au client.

  2. Envoyer le HTML au client + le bundle JavaScript qui va permettre de construire la page (le Client Component), sans tenir compte de la Promise (en réalité la résolution de la Promise a déjà commencé côté serveur).

Les réponses du serveur portent le header Transfer-Encoding: chunked pour indiquer que la réponse est découpée en plusieurs parties. À ce stade, la connexion est maintenue ouverte pour recevoir les futurs chunks.

  1. Lorsque la Promise est résolue côté serveur, celui-ci envoie un dernier chunk sur la connexion maintenue ouverte jusqu'à présent.

  2. Le client va recevoir le dernier chunk et va pouvoir construire la page avec les données récupérées.

À ce stade, on voit déjà l'avantage majeur de cette approche qui permet d'exécuter une fonction asynchrone côté serveur sans bloquer le rendu de la page et sans utiliser de server actions impliquant un nouvel appel HTTP.

⚠️ Notez que la fonction asynchrone sera exécutée même si elle n'est pas consommée par le Client Component. Veillez à ne pas laisser de Promise inutiles dans le code, cela pourrait avoir un impact sur les performances.

Comment fonctionne l'API use ?

Visuellement, il n'y a pas beaucoup de changement... pour l'instant, car on n'exploite pas le fait d'avoir un rendu non-bloquant, mais c'est là que l'API use intervient. Elle va nous permettre de cibler le composant qui doit attendre la résolution de la Promise et d'afficher un fallback en attendant ou une erreur si la Promise est rejetée.

Si le composant PlanetsPage contient des méta-données, comme un titre ou une description, ceux-ci seront affichés avant que la Promise soit résolue. Idem pour les éventuels layouts ou autres éléments autres que le composant Planets. Ce qui va rendre la page visuellement plus fluide pour l'utilisateur.

Pour profiter des avantages de l'API use, nous allons donc wrapper le composant Planets dans un Suspense et/ou un ErrorBoundary et utiliser use dans le composant client Planets.

app/planets/page.tsx
import { Suspense } from 'react'
import { ErrorBoundary } from 'react-error-boundary'
import Planets from './Planets'
import { getPlanets, type Planet } from '@/lib/planets'

export default function PlanetsPage() {
  const planetsPromise: Promise<Planet[]> = getPlanets() // Récupération asynchrone des données

  return (
    <ErrorBoundary fallback={<div>Error</div>}>
      <Suspense fallback={<div>Loading...</div>}>
        <Planets planetsPromise={planetsPromise} />
      </Suspense>
    </ErrorBoundary>
  )
}
app/planets/Planets.tsx
'use client'

import { use } from 'react'

export default function Planets({ planetsPromise }) {
  const planets = use(planetsPromise)

  return (
    <ul>
      {planets.map(planet => (
        <li key={planet.id}>{planet.name}</li>
      ))}
    </ul>
  )
}

Ici, React va détecter que le composant Planets utilise l'API use sur une Promise, il va remplacer le composant Planets par le fallback du Suspense dans l'arbre de composants et restaurer le composant Planets lorsque la Promise sera résolue, ou afficher l'erreur si la Promise est rejetée.

Passage de Promises entre Client Components

L'objectif premier de cette nouvelle API est avant tout de pouvoir contrôler les états de chargement et d'erreur lors de la récupération de données, mais on peut aussi l'utiliser pour aller plus loin dans la granularité du data fetching et faire "descendre" notre état de chargement au plus proche des composants concernés. Parfois, cela va nous pousser à réorganiser nos composants pour les rendre plus petits et plus indépendants, mais au final cela nous permettra de gagner en lisibilité et maintenabilité en plus d'améliorer l'expérience utilisateur.

Autre cas d'utilisation

Parmi les autres cas d'utilisation de l'API use, on peut citer :

  • utilisable dans des Server Components
  • utilisable de manière conditionnelle
  • utilisable pour récupérer des données d'un Contexte

Inconvénients

Hélas, l'API use nécessite de mettre en place un Suspense et/ou un ErrorBoundary pour chaque composant qui l'utilise. Cela peut devenir rapidement fastidieux à gérer, et donner une sensation de boilerplate.

Les fichiers loading.tsx et error.tsx peuvent être utilisés pour gérer les états de chargement et d'erreur de manière globale ou par page. Ils ne répondent pas au même niveau de granularité qu'un Suspense ciblé sur un composant mais peuvent prévenir d'oublis potentiels.

Conclusion

Si vous souhaitez optimiser l'expérience utilisateur de vos pages, l'API use est une solution à ne pas négliger, si vos fonctions asynchrones ne sont pas dépendantes d'une interaction utilisateur. Vous pourrez ainsi cibler les composants concernés par un état de loading ou d'erreur et éviter des états de "flash" qui pourraient survenir avec la gestion des états de chargement classique.

Autre avantage, et pas des moindres, c'est que désormais vos Server Components pourront être rendus immédiatement sans attendre la résolution de la Promise.

Sources

À découvrir également

Comment construire des applications IA avec Vercel AI SDK — Part I

06 Sep 2024

Comment construire des applications IA avec Vercel AI SDK — Part I

Vercel a dévoilé une nouvelle version de Vercel AI SDK, conçu pour simplifier le processus de développement d'applications IA en fournissant des outils et des bibliothèques prêts à l'emploi pour les développeurs. Je vous propose un tour d'horizon des exemples clés abordés par Nico Albanese, ingénieur chez Vercel, dans sa vidéo didactique publiée sur YouTube.

par

Vincent

AI et UI #1 - Filtres intelligents avec le SDK Vercel AI et Next.js

12 Jun 2024

AI et UI #1 - Filtres intelligents avec le SDK Vercel AI et Next.js

Dans ce premier article d’une série consacrée à l’IA et l’UI, je vous propose de découvrir différentes manières d’intégrer ces modèles d’IA dans vos applications React pour améliorer l’expérience utilisateur.

par

Baptiste

Retour d'expérience chez 20 Minutes : s'adapter au journalisme numérique

30 May 2024

Retour d'expérience chez 20 Minutes : s'adapter au journalisme numérique

Dans cet article, vous ne trouverez pas de snippets ou de tips croustillants sur React, seulement le récit d'une aventure plutôt ordinaire à travers le développement et l'évolution d'un projet technique.

par

Vincent

Premier Octet vous accompagne dans le développement de vos projets avec nextjs

En savoir plusNous contacter
18 avenue Parmentier
75011 Paris
+33 1 43 57 39 11
hello@premieroctet.com

Suivez nos aventures

GitHub
X (Twitter)
Flux RSS

Naviguez à vue