Erreurs React & Next.js
Les boss de donjon : hydration, SSR, build errors.
5.1Hydration Error : le boss le plus fourbe
L'erreur d'hydratation se produit quand le HTML genere par le serveur ne correspond pas a ce que React genere cote client. C'est comme si le plan du donjon changeait entre deux visites.
// CAUSE 1 : Utiliser Date() ou Math.random() dans le render
// Le serveur genere une valeur, le client en genere une autre
function BadComponent() {
return <p>Il est {new Date().toLocaleString()}</p> // Hydration error !
}
// FIX : useEffect pour les valeurs dynamiques
function GoodComponent() {
const [time, setTime] = useState("")
useEffect(() => setTime(new Date().toLocaleString()), [])
return <p>Il est {time}</p>
}
// CAUSE 2 : Balises mal imbriquees
// <p> ne peut pas contenir <div>
function Bad() {
return <p><div>Contenu</div></p> // Hydration error !
}
// CAUSE 3 : Extensions navigateur qui modifient le DOM
// Solution : verifier en navigation privee5.2"use client" : la frontiere serveur/client
// ERREUR : utiliser useState dans un Server Component
// app/page.tsx (Server Component par defaut)
import { useState } from 'react' // Erreur au build !
export default function Page() {
const [count, setCount] = useState(0) // Hooks = client only !
return <p>{count}</p>
}
// FIX : ajouter 'use client' OU extraire dans un composant client
// components/Counter.tsx
'use client'
import { useState } from 'react'
export function Counter() {
const [count, setCount] = useState(0)
return <button onClick={() => setCount(c => c + 1)}>{count}</button>
}
// app/page.tsx (reste Server Component)
import { Counter } from '@/components/Counter'
export default function Page() {
return <Counter />
}5.3Build errors : le gardien du deploiement
Le build est le gardien final. Il est plus strict que npm run dev : ce qui passe en dev peut echouer au build.
# ERREUR 1 : Type manquant
# "Type error: Property 'name' does not exist on type..."
# -> Tu as un typo ou un type incorrect. Verifie tes interfaces.
# ERREUR 2 : Import manquant ou circulaire
# "Module not found: Can't resolve './component'"
# -> Verifie le chemin relatif et l'export du fichier.
# ERREUR 3 : Dynamic import avec SSR
# "window is not defined"
# -> Le code accede a window dans un Server Component.
# ERREUR 4 : generateStaticParams manquant
# "Error: Page with dynamic route /[slug] requires generateStaticParams"
# -> Ajoute la fonction generateStaticParams dans ton page.tsx5.4window is not defined (SSR)
window, document et localStorage n'existent pas cote serveur. Si tu les utilises dans un Server Component ou au top-level d'un module, ca plante.
// ERREUR : au top-level du module
const theme = localStorage.getItem('theme') // ReferenceError: localStorage is not defined
// FIX 1 : dans un useEffect (composant client)
'use client'
import { useState, useEffect } from 'react'
function ThemeProvider() {
const [theme, setTheme] = useState('light')
useEffect(() => {
const saved = localStorage.getItem('theme')
if (saved) setTheme(saved)
}, [])
return <div data-theme={theme}>...</div>
}
// FIX 2 : guard typeof window
const isClient = typeof window !== 'undefined'
const theme = isClient ? localStorage.getItem('theme') : 'light'5.5"async Server Component"
// Dans Next.js 15+, les Server Components PEUVENT etre async
// Mais les Client Components ne le peuvent PAS
// OK : Server Component async
export default async function Page() {
const data = await fetch('https://api.example.com/data')
const json = await data.json()
return <div>{json.title}</div>
}
// ERREUR : Client Component async
'use client'
export default async function Page() { // Interdit !
const data = await fetch('/api/data')
return <div>{data}</div>
}
// FIX : utiliser useEffect dans un Client Component
'use client'
export default function Page() {
const [data, setData] = useState(null)
useEffect(() => {
fetch('/api/data').then(r => r.json()).then(setData)
}, [])
return <div>{data?.title}</div>
}5.6Le guide anti-boss
| Boss | Symptome | Solution |
|---|---|---|
| Hydration error | HTML serveur != client | useEffect pour valeurs dynamiques |
| Hooks in SC | useState dans Server Component | Ajouter 'use client' |
| window undefined | localStorage/window en SSR | Guard typeof window ou useEffect |
| Build type error | Types incorrects | Verifier interfaces TS |
| Async client | async dans 'use client' | Utiliser useEffect + useState |