7.1 — Concepts communs
Débutant
🎯 Objectif : avant de plonger dans React, comprendre les idées partagées par tous les frameworks UI modernes. Une fois ces concepts assimilés, apprendre Vue ou Svelte demande quelques heures, pas des semaines.
À l'issue de cet axe, tu sauras :
- Définir un composant et ses 3 dimensions : props, état, événements
- Distinguer virtual DOM, compilation, fine-grained reactivity
- Comprendre le re-rendu et savoir éviter les rendus inutiles
- Connaître les options de routing client (file-based, programmatique)
- Choisir entre état local, contexte, état global
Le composant — l’unité de tout
Section intitulée « Le composant — l’unité de tout »Un composant combine 3 choses :
Données (props + état) → Rendu (HTML) → Événements ↓ modifient l'état ↓ re-renduVocabulaire universel
Section intitulée « Vocabulaire universel »| Terme | Sens |
|---|---|
| Props | Données reçues du parent (en lecture seule du point de vue de l’enfant) |
| État (state) | Données internes du composant qui peuvent changer |
| Rendu | La fonction qui transforme (props, state) en HTML |
| Événements | Actions utilisateur (clic, saisie, scroll…) qui peuvent muter l’état |
| Cycle de vie | Hooks à des moments clés : monté, mis à jour, démonté |
Tout framework UI moderne (React, Vue, Svelte, Angular, Solid…) tourne autour de ces 5 mots.
Composition
Section intitulée « Composition »Un composant peut contenir d’autres composants. C’est la composition, le pilier de la conception moderne.
// Pseudo-code, valable en React/Vue/Svelte avec syntaxe différente<Page> <Header user={currentUser} /> <Sidebar items={menu} /> <Main> <ArticleList articles={articles} /> </Main> <Footer /></Page>C’est l’équivalent moderne des templates côté serveur (Twig, Blade, EJS), mais avec un état dynamique côté client.
Approches de réactivité
Section intitulée « Approches de réactivité »Quand l’état change, comment le framework met-il à jour le DOM ?
1. Virtual DOM (React, Vue)
Section intitulée « 1. Virtual DOM (React, Vue) »À chaque changement, le framework :
- Re-exécute la fonction de rendu → produit un nouvel arbre virtuel.
- Compare avec l’ancien (diffing).
- Applique uniquement les changements au DOM réel.
flowchart LR
State[Nouvel état] --> Render[Re-render<br/>fonction]
Render --> NewVDOM[Nouveau VDOM]
OldVDOM[Ancien VDOM] --> Diff{diff}
NewVDOM --> Diff
Diff --> Patch[Patch minimal au DOM] ✅ Très flexible (n’importe quelle structure JSX/template). ❌ Coût du diff à chaque changement. ❌ Tout l’arbre du composant et de ses enfants se ré-exécute.
2. Fine-grained reactivity (Solid, Svelte 5, Vue 3 refs)
Section intitulée « 2. Fine-grained reactivity (Solid, Svelte 5, Vue 3 refs) »Chaque morceau d’état réactif sait quels effets dépendent de lui. Quand il change, seuls ces effets s’exécutent.
// Pseudo-code Solidconst [count, setCount] = createSignal(0);
createEffect(() => { console.log(count()); // ne s'exécute QUE si count change});
// Ce composant ne re-rend pas — seul l'effet ciblé tourne✅ Performances brutales (pas de diff). ✅ Updates ciblées au DOM. ❌ Modèle mental plus subtil (dépendances implicites).
3. Compilation (Svelte, Solid)
Section intitulée « 3. Compilation (Svelte, Solid) »Le framework compile ton code en JavaScript optimisé qui modifie le DOM directement, sans VDOM ni runtime de réactivité lourd.
<!-- Svelte --><script> let count = $state(0);</script>
<button on:click={() => count++}> Compteur : {count}</button>À la compilation, ça devient du JS direct qui sait que cliquer le bouton incrémente une variable et met à jour le textContent du bouton.
✅ Bundles minuscules (Svelte ~5 Ko gzippé). ✅ Performances excellentes.
Verdict 2026
Section intitulée « Verdict 2026 »| Approche | Frameworks | Quand préférer |
|---|---|---|
| Virtual DOM | React, Vue | Écosystème énorme, équipe nombreuse |
| Fine-grained | Solid, Svelte 5 | Performance critique, app très interactive |
| Compilation | Svelte, Astro | Sites avec peu d’interactivité, bundle minimaliste |
Le re-rendu — comprendre quand et pourquoi
Section intitulée « Le re-rendu — comprendre quand et pourquoi »En virtual DOM (React/Vue), un composant re-rend quand :
- Son état change (
setState). - Ses props changent.
- Le contexte qu’il consomme change.
- Son parent re-rend (et cascade).
// React — exemple typiquefunction Parent() { const [count, setCount] = useState(0); return ( <> <ChildA /> {/* re-rend même si rien ne le concerne */} <ChildB count={count} /> </> );}À chaque clic, ChildA re-rend aussi alors que ses props n’ont pas changé. Solutions :
React.memo: skip le re-rendu si props identiques.- Découper l’état : mettre
countplus bas dans l’arbre. - Frameworks fine-grained : pas le problème.
Cycle de vie
Section intitulée « Cycle de vie »3 moments universels :
| Moment | React (hooks) | Vue (Options API) | Svelte |
|---|---|---|---|
| Monté (DOM créé) | useEffect(() => {...}, []) | mounted() | onMount(() => {...}) |
| Mis à jour (re-rendu) | useEffect(() => {...}, [dep]) | watch(dep, () => {...}) | $effect(() => {...}) (Svelte 5) |
| Démonté (DOM retiré) | useEffect(() => () => cleanup, []) | unmounted() | onDestroy() |
Cas d’usage du cycle de vie
Section intitulée « Cas d’usage du cycle de vie »// ReactuseEffect(() => { // Au montage : abonnement const subscription = api.subscribe(handler);
// Au démontage : désabonnement (return) return () => subscription.unsubscribe();}, []);Toujours se désabonner dans le démontage. Sinon : memory leak + bug si le composant remonte.
Routing client
Section intitulée « Routing client »Une SPA change l’URL et la vue sans recharger la page. Deux approches :
Routing programmatique (React Router v6, Vue Router)
Section intitulée « Routing programmatique (React Router v6, Vue Router) »// React Router<BrowserRouter> <Routes> <Route path="/" element={<Home />} /> <Route path="/products/:id" element={<Product />} /> <Route path="*" element={<NotFound />} /> </Routes></BrowserRouter>Configuration explicite des routes dans le code.
Routing par fichiers (Next.js, Nuxt, SvelteKit, Astro)
Section intitulée « Routing par fichiers (Next.js, Nuxt, SvelteKit, Astro) »app/├── page.tsx → /├── products/│ └── [id]/│ └── page.tsx → /products/:id└── about/ └── page.tsx → /aboutL’arborescence des fichiers est la table de routes. Plus déclaratif, moins de boilerplate.
Tendance 2026 : la plupart des nouveaux projets utilisent du file-based routing via un méta-framework.
Gestion d’état — 3 niveaux
Section intitulée « Gestion d’état — 3 niveaux »Niveau 1 — Local (state du composant)
Section intitulée « Niveau 1 — Local (state du composant) »const [count, setCount] = useState(0);90 % des cas. Si seul un composant et ses enfants directs ont besoin d’une donnée, garde-la locale.
Niveau 2 — Partagé via props ou contexte
Section intitulée « Niveau 2 — Partagé via props ou contexte »Lifting state up : si 2 frères ont besoin de la même donnée, mets-la dans leur parent commun et passe en props.
Si les enfants sont profondément imbriqués → contexte :
// React Contextconst ThemeContext = createContext('light');
<ThemeContext.Provider value={theme}> <App /> {/* tous les descendants peuvent useContext(ThemeContext) */}</ThemeContext.Provider>Niveau 3 — État global (store)
Section intitulée « Niveau 3 — État global (store) »Quand beaucoup de composants distants partagent la même donnée, ou que la logique est complexe.
Options modernes :
| Lib | Style | Forces |
|---|---|---|
| Zustand (React) | Hooks simples, sans provider | Minimaliste, ergonomique |
| Redux Toolkit | Reducers, actions | Convient aux grosses équipes, devtools puissants |
| Jotai (React) | Atoms primitifs | Très granulaire |
| Pinia (Vue) | Stores typés | Le standard Vue depuis Vuex |
| Svelte stores | Natif Svelte | writable(), $store |
// Zustand — exempleimport { create } from 'zustand';
const useCart = create((set) => ({ items: [], add: (item) => set((s) => ({ items: [...s.items, item] })), clear: () => set({ items: [] }),}));
// Dans un composantfunction Cart() { const items = useCart((s) => s.items); return <div>{items.length} articles</div>;}Server state vs client state
Section intitulée « Server state vs client state »Distinction importante : les données serveur (liste de produits, profil utilisateur, etc.) ont leur propre lib spécialisée.
- TanStack Query (React, Vue, Svelte, Solid) : cache, refetch, mutations, devtools.
- SWR (React, Vercel) : équivalent plus léger.
Ces libs résolvent le caching, la synchronisation, le revalidate-on-focus, la pagination, et les mutations optimistes — choses pénibles à gérer manuellement.
// TanStack Queryfunction Users() { const { data, isLoading, error } = useQuery({ queryKey: ['users'], queryFn: () => fetch('/api/users').then(r => r.json()), });
if (isLoading) return <Spinner />; if (error) return <Error message={error.message} />; return <UserList users={data} />;}Styling dans un framework
Section intitulée « Styling dans un framework »3 approches majeures :
CSS classique + classes
Section intitulée « CSS classique + classes »import './Button.css';<button className="btn btn-primary">Click</button>Simple. Risque de conflits de noms. Solution : CSS Modules (Button.module.css) qui scope les classes localement.
CSS-in-JS
Section intitulée « CSS-in-JS »// styled-componentsconst Button = styled.button` background: var(--primary); padding: 0.5rem 1rem;`;Pratique pour les composants dynamiques. Mais : runtime cost, complexité, fall en disgrâce avec RSC.
Utility-first (Tailwind)
Section intitulée « Utility-first (Tailwind) »<button className="bg-blue-500 hover:bg-blue-700 text-white px-4 py-2 rounded"> Click</button>Le standard en 2026 dans la plupart des projets greenfield. Voir 7.6.
Auto-évaluation
Section intitulée « Auto-évaluation »Pour aller plus loin
Section intitulée « Pour aller plus loin »- Patterns.dev — patterns.dev — patterns de rendu et de chargement
- Thinking in React (officiel) — react.dev/learn/thinking-in-react
- Reactivity Compared — comparaison vidéo des 3 modèles de réactivité
Suite : 7.2 — React — le framework dominant et son écosystème.