Data Fetching
Récupère des données depuis n'importe où. Serveur, API, base de données... Next.js gère tout.
5.1Fetch dans un Server Component
Le plus beau avec les Server Components : tu peux utiliser fetch ou async/await directement dans ton composant. Pas besoin de useEffect, pas besoin de state de chargement.
// app/blog/page.tsx (Server Component)
interface Article {
id: number
title: string
body: string
}
export default async function BlogPage() {
const res = await fetch('https://jsonplaceholder.typicode.com/posts')
const articles: Article[] = await res.json()
return (
<main>
<h1>Mon blog</h1>
<ul>
{articles.slice(0, 5).map((article) => (
<li key={article.id}>
<h2>{article.title}</h2>
<p>{article.body.slice(0, 100)}...</p>
</li>
))}
</ul>
</main>
)
}C'est tout. Pas de useState, pas de useEffect, pas de loading à gérer à la main. Le composant est async, il attend les données, et rend le HTML directement. L'utilisateur reçoit une page complète.
5.2Le cache intelligent
Next.js est malin avec les requêtes. Par défaut, les résultats de fetch sont mis en cache. Ça veut dire que si deux visiteurs demandent la même page, Next.js ne refait pas le fetch : il sert le résultat du cache.
Tu peux contrôler ce comportement :
// Données toujours fraîches (pas de cache)
const res = await fetch('https://api.example.com/data', {
cache: 'no-store'
})
// Revalider toutes les 60 secondes
const res = await fetch('https://api.example.com/data', {
next: { revalidate: 60 }
})| Option | Comportement | Cas d'usage |
|---|---|---|
| Par défaut | Cache permanent | Contenu statique (pages marketing) |
cache: 'no-store' | Jamais de cache | Données temps réel (cours de bourse) |
next: { revalidate: 60 } | Cache + refresh toutes les 60s | Blog, catalogue (bon compromis) |
5.3Server Actions : les formulaires nouvelle génération
Les Server Actions, c'est la fonctionnalité qui change tout pour les formulaires. Au lieu de créer une API, de faire un fetch POST côté client, de gérer l'état de chargement... tu écris une fonction serveur et tu la branches directement sur ton formulaire.
// app/contact/page.tsx
export default function ContactPage() {
async function envoyerMessage(formData: FormData) {
'use server'
const nom = formData.get('nom')
const message = formData.get('message')
// Ici tu peux sauvegarder en BDD, envoyer un email...
console.log(`Message de ${nom}: ${message}`)
}
return (
<form action={envoyerMessage}>
<input name="nom" placeholder="Ton nom" required />
<textarea name="message" placeholder="Ton message" required />
<button type="submit">Envoyer</button>
</form>
)
}La directive 'use server' dans la fonction dit à Next.js : "Cette fonction tourne sur le serveur." Le formulaire l'appelle directement, sans API intermédiaire. C'est magiquement simple.
5.4Récupérer des données dynamiques par route
La combinaison route dynamique + fetch est ultra puissante. Par exemple, une page produit :
// app/produits/[id]/page.tsx
interface Produit {
id: number
title: string
price: number
description: string
}
export default async function ProduitPage({
params,
}: {
params: Promise<{ id: string }>
}) {
const { id } = await params
const res = await fetch(`https://fakestoreapi.com/products/${id}`)
const produit: Produit = await res.json()
return (
<main>
<h1>{produit.title}</h1>
<p>{produit.description}</p>
<p className="text-2xl font-bold">{produit.price} €</p>
</main>
)
}Chaque URL (/produits/1, /produits/42) affiche le bon produit. La donnée est récupérée côté serveur, le HTML est envoyé complet au navigateur. L'utilisateur voit le contenu instantanément.
5.5Gérer le chargement avec loading.tsx
Si le fetch prend du temps, rappelle-toi : tu peux créer un fichier loading.tsx dans le même dossier. Next.js l'affiche automatiquement pendant que les données arrivent.
// app/produits/[id]/loading.tsx
export default function Loading() {
return (
<div className="animate-pulse">
<div className="h-8 bg-slate-200 rounded w-3/4 mb-4" />
<div className="h-4 bg-slate-200 rounded w-full mb-2" />
<div className="h-4 bg-slate-200 rounded w-2/3" />
</div>
)
}Ce "skeleton" (squelette grisé) donne l'impression que la page charge vite, même si le serveur est en train de récupérer les données. C'est une très bonne pratique UX.