Esc
 Naviguer  Ouvrir Esc Fermer
Aller au contenu

7.1 — Concepts communs

Débutant 25 min prérequis : axe 6 lu

🎯 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

Un composant combine 3 choses :

Données (props + état) → Rendu (HTML) → Événements
modifient l'état
re-rendu
TermeSens
PropsDonné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
RenduLa fonction qui transforme (props, state) en HTML
ÉvénementsActions utilisateur (clic, saisie, scroll…) qui peuvent muter l’état
Cycle de vieHooks à des moments clés : monté, mis à jour, démonté

Tout framework UI moderne (React, Vue, Svelte, Angular, Solid…) tourne autour de ces 5 mots.

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.

Quand l’état change, comment le framework met-il à jour le DOM ?

À chaque changement, le framework :

  1. Re-exécute la fonction de rendu → produit un nouvel arbre virtuel.
  2. Compare avec l’ancien (diffing).
  3. 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]
Virtual DOM — diff entre 2 arbres

✅ 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 Solid
const [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).

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.

ApprocheFrameworksQuand préférer
Virtual DOMReact, VueÉcosystème énorme, équipe nombreuse
Fine-grainedSolid, Svelte 5Performance critique, app très interactive
CompilationSvelte, AstroSites avec peu d’interactivité, bundle minimaliste

En virtual DOM (React/Vue), un composant re-rend quand :

  1. Son état change (setState).
  2. Ses props changent.
  3. Le contexte qu’il consomme change.
  4. Son parent re-rend (et cascade).
// React — exemple typique
function 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 count plus bas dans l’arbre.
  • Frameworks fine-grained : pas le problème.

3 moments universels :

MomentReact (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()
// React
useEffect(() => {
// 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.

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 → /about

L’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.

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.

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 Context
const ThemeContext = createContext('light');
<ThemeContext.Provider value={theme}>
<App /> {/* tous les descendants peuvent useContext(ThemeContext) */}
</ThemeContext.Provider>

Quand beaucoup de composants distants partagent la même donnée, ou que la logique est complexe.

Options modernes :

LibStyleForces
Zustand (React)Hooks simples, sans providerMinimaliste, ergonomique
Redux ToolkitReducers, actionsConvient aux grosses équipes, devtools puissants
Jotai (React)Atoms primitifsTrès granulaire
Pinia (Vue)Stores typésLe standard Vue depuis Vuex
Svelte storesNatif Sveltewritable(), $store
// Zustand — exemple
import { create } from 'zustand';
const useCart = create((set) => ({
items: [],
add: (item) => set((s) => ({ items: [...s.items, item] })),
clear: () => set({ items: [] }),
}));
// Dans un composant
function Cart() {
const items = useCart((s) => s.items);
return <div>{items.length} articles</div>;
}

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 Query
function 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} />;
}

3 approches majeures :

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.

// styled-components
const 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.

<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.

React, à chaque setState, fait quoi sur l'arbre des composants par défaut ?
Tu as un composant React avec 3 useState. L'utilisateur tape dans un input lié au state #1. Que se passe-t-il ?
Tu commences un projet front avec une équipe de 5 devs. Quelle gestion d'état ?

Suite : 7.2 — React — le framework dominant et son écosystème.