
'use client'À la fin du chapitre précédent, nous avons ajouté 'use client' en haut du fichier Navigation.js pour pouvoir utiliser usePathname() et afficher la route active.
Vous vous êtes peut-être demandé : pourquoi cette directive 'use client' ? C'est exactement ce que nous allons comprendre dans ce chapitre !
Reprenons le code de votre navigation :
'use client'
import { usePathname } from 'next/navigation'
import Link from 'next/link'
import styles from './Navigation.module.css'
export default function Navigation() {
const pathname = usePathname()
return (
<nav className={styles.nav}>
{/* ... */}
<Link
href="/projects"
className={pathname === '/projects' ? `${styles.link} ${styles.active}` : styles.link}
>
Projets
</Link>
{/* ... */}
</nav>
)
}Que fait ce code ?
usePathname()récupère l'URL actuelle, par exemple/projects
Le composant compare l'URL avec chaque lien
Si l'URL correspond, le lien reçoit la classe active.
Avec React classique (Vite), tous vos composants s'exécutent dans le navigateur. Vous pouvez utiliser useState , useEffect , et tous les hooks sans restriction.
Next.js fonctionne différemment : par défaut, vos composants sont des Server Components qui s'exécutent côté serveur !
// app/about/page.js - Server Component par défaut ✅
export default function About() {
return (
<div>
<h1>À propos de moi</h1>
<p>Développeur web passionné...</p>
</div>
)
}Ce composant est rapide car :
Le HTML est généré côté serveur
Aucun JavaScript n'est envoyé au navigateur pour ce composant
Le contenu est immédiatement visible (SEO optimal)
Mais les Server Components ont des limitations :
Pas de hooks commeuseState,useEffect,usePathname
Pas d'événements (onClick,onChange, etc.)
Pas d'accès aux APIs du navigateur (window,localStorage, etc.)
Pour créer un Client Component, ajoutez 'use client' en première ligne :
'use client'
import { useState } from 'react'
export default function Counter() {
const [count, setCount] = useState(0)
return (
<button onClick={() => setCount(count + 1)}>
Compteur : {count}
</button>
)
}Les Client Components peuvent :
Utiliser tous les hooks React (useState,useEffect,usePathname, etc.)
Gérer les événements utilisateur (onClick,onChange, etc.)
Utiliser les APIs du navigateur (window,localStorage, etc.)
Créer de l'interactivité
Navigation est un Client ComponentRevenons à notre navigation. Elle utilise usePathname() qui a besoin de lire l'URL dans le navigateur pour savoir quelle page est active.
'use client' // ← Nécessaire pour utiliser usePathname()
import { usePathname } from 'next/navigation'
export default function Navigation() {
const pathname = usePathname() // ← Ce hook lit l'URL côté client
// Compare l'URL avec chaque lien pour appliquer la classe active
return (
<Link
href="/projects"
className={pathname === '/projects' ? 'active' : ''}
>
Projets
</Link>
)
}Sans 'use client' , vous auriez eu cette erreur :
Error: usePathname only works in Client Components
Pourquoi préférer les Server Components ?
Plus rapides (moins de JavaScript envoyé au navigateur)
Plus sécurisés (le code reste sur le serveur)
Meilleurs pour le SEO (HTML complet immédiatement disponible)
Quand utiliser un Client Component ?
Vous avez besoin de hooks (useState,useEffect,usePathname, etc.)
Vous gérez des événements (onClick,onChange, etc.)
Vous utilisez les APIs du navigateur
Améliorons votre navigation avec un vrai menu burger pour mobile qui s'ouvre et se ferme au clic !
Modifiez app/components/Navigation/Navigation.js :
'use client'
import { useState } from 'react'
import Link from 'next/link'
import { usePathname } from 'next/navigation'
import styles from './Navigation.module.css'
export default function Navigation() {
const [isOpen, setIsOpen] = useState(false)
const pathname = usePathname()
const toggleMenu = () => {
setIsOpen(!isOpen)
}
const closeMenu = () => {
setIsOpen(false)
}
return (
<nav className={styles.nav}>
<div className={styles.container}>
<Link href="/" className={styles.logo} onClick={closeMenu}>
Mon Portfolio
</Link>
{/* Bouton burger pour mobile */}
<button
className={styles.burger}
onClick={toggleMenu}
aria-label="Menu"
>
<span className={isOpen ? styles.burgerOpen : ''}></span>
<span className={isOpen ? styles.burgerOpen : ''}></span>
<span className={isOpen ? styles.burgerOpen : ''}></span>
</button>
{/* Menu /}
<ul className={`${styles.menu} ${isOpen ? styles.menuOpen : ''}`}>
{/* liens du menu*/}
</ul>
</div>
</nav>
)
}Ce qui a changé :
useState(false): Gère l'état ouvert/fermé du menu burger
toggleMenu(): Inverse l'état (ouvert ↔ fermé)
closeMenu(): Ferme le menu quand on clique sur un lien
Bouton burger : Trois barres qui s'animent en croix quand le menu est ouvert
Classes conditionnelles :menuOpenetburgerOpenappliquées selon l'état
Pourquoi c'est un Client Component ?
UtiliseuseStatepour gérer l'état du menu
UtiliseonClickpour réagir aux clics
UtiliseusePathnamepour le highlighting actif
Testez ! Réduisez la fenêtre de votre navigateur, cliquez sur l'icône burger. Le menu s'ouvre avec une animation fluide depuis la droite, et les trois barres se transforment en croix !
'use client'Ne mettez 'use client' que sur les composants qui ont vraiment besoin d'interactivité.
❌ Voici un mauvais exemple :
'use client' // ❌ Pas nécessaire ici !
export default function ProjectCard({ title, description }) {
return (
<div>
<h2>{title}</h2>
<p>{description}</p>
</div>
)
}Ce composant est purement visuel, pas d'interactivité → Gardez-le en Server Component !
✅ Voici un bon exemple :
// Pas de 'use client' = Server Component par défaut ✅
export default function ProjectCard({ title, description }) {
return (
<div>
<h2>{title}</h2>
<p>{description}</p>
</div>
)
}Au lieu de rendre toute une page "client", isolez seulement la partie interactive.
❌ Mauvais exemple :
'use client' // ❌ Toute la page devient Client Component
import { useState } from 'react'
export default function Projects() {
const [filter, setFilter] = useState('all')
return (
<div>
<h1>Mes Projets</h1>
{/* Beaucoup de contenu statique... */}
<select onChange={(e) => setFilter(e.target.value)}>
<option value="all">Tous</option>
<option value="web">Web</option>
</select>
{/* Plus de contenu statique... */}
</div>
)
}Ici, tout le contenu statique devient Client Component alors que seul le <select> a besoin d'interactivité.
✅ Bon exemple :
// projects/page.js - Server Component ✅
import ProjectFilter from './ProjectFilter'
export default function Projects() {
return (
<div>
<h1>Mes Projets</h1>
{/* Contenu statique reste Server Component */}
<ProjectFilter /> {/* Seul ce composant est Client */}
{/* Plus de contenu statique Server Component */}
</div>
)
}
// ProjectFilter.js - Client Component
'use client'
import { useState } from 'react'
export default function ProjectFilter() {
const [filter, setFilter] = useState('all')
return (
<select onChange={(e) => setFilter(e.target.value)}>
<option value="all">Tous</option>
<option value="web">Web</option>
</select>
)
}Avantages :
Moins de JavaScript envoyé au navigateur
Meilleure performance
Meilleur SEO (le contenu statique reste en Server Component)
✅ Bon exemple :
'use client'
import { useState } from 'react'
export default function ClientParent({ children }) {
const [count, setCount] = useState(0)
return (
<div>
<button onClick={() => setCount(count + 1)}>+</button>
{children} {/* ✅ Le Server Component est passé en children */}
</div>
)
}
// page.js
import ClientParent from './ClientParent'
import ServerChild from './ServerChild' // Server Component
export default function Page() {
return (
<ClientParent>
<ServerChild /> {/* ✅ Fonctionne ! */}
</ClientParent>
)
}
Avant de passer au chapitre suivant, entraînez-vous :
Pour l’instant votre formulaire n’est pas vraiment utile. Utilisez vos connaissances de React et des composants clients pour rendre le formulaire interactif.
Dans la solution d’exemple nous avons creé un composant ContactForm.js pour extraire la logique client du formulaire.
Pourquoi ContactForm est un Client Component ?
Il utilise useState pour gérer les données du formulaire et le statut
Gère les événementsonChange et onSubmit
A un affichage conditionnel basé sur l'état
Testez : Remplissez le formulaire et envoyez-le. Un message de confirmation s'affiche pendant l'envoi, puis un message de succès apparaît !
Félicitations ! Vous maîtrisez maintenant les bases des Server et Client Components de Next.js.
Les Server Components, par défaut dans Next.js, s'exécutent côté serveur.
Les Client Components permettent l'interactivité (hooks, événements) : Ajoutez 'use client' en première ligne.
Utilisez des Server Components par défaut, ne passez en Client Component que si nécessaire.
Isolez l'interactivité dans des sous-composants, minimisez l'usage de 'use client' et gardez le maximum de contenu en Server Components.
Voici les Hooks que nous avons utilisés :useStategère l'état local ;useEffectgère les effets de bord (scroll, événements, localStorage) ;usePathnamedétècte de la route active.
Dans le prochain chapitre nous verrons comment récupérer et afficher des données dynamiques dans votre portfolio avec le data fetching !