Qu’est-ce que React ?
React est une bibliothèque JavaScript permettant de construire des interfaces utilisateur à partir de composants. Un composant est une fonction qui retourne du balisage, et vous assemblez ces composants pour construire une page. Au lieu d’indiquer au navigateur comment modifier le DOM étape par étape, vous décrivez à quoi l’UI doit ressembler en fonction des données actuelles, et React se charge d’effectuer les mises à jour.
Ce changement de paradigme est appelé le rendu déclaratif, et c’est pour cela que React a semblé novateur en 2013. Vous ne rédigez plus “trouve cet élément, change son texte, bascule cette classe”, mais vous écrivez “étant donné cet état, voici l’écran”. La partie complexe — le diffing et la mise à jour efficace du DOM — devient le travail de React.
Composants et JSX
Un composant React est une fonction dont le nom commence par une majuscule et qui retourne du JSX.
// Welcome.jsx
function Welcome({ name }) {
return <h1>Hello, {name}!</h1>;
}
export default function App() {
return (
<main>
<Welcome name="Ada" />
<Welcome name="Grace" />
</main>
);
}
Le JSX ressemble à du HTML, mais c’est du JavaScript. Les accolades permettent d’intégrer des expressions, et le compilateur traduit chaque élément en un appel de fonction. Comme les composants ne sont que des fonctions, vous pouvez les composer, les imbriquer et les réutiliser de la même manière que n’importe quelle autre fonction.
Props
Les props sont les entrées d’un composant. Elles circulent vers le bas, du parent vers l’enfant, et sont en lecture seule — un enfant ne doit jamais modifier ses props.
// Card.jsx
function Card({ title, children, variant = "default" }) {
return (
<article className={`card card--${variant}`}>
<h3>{title}</h3>
{children}
</article>
);
}
La prop children correspond à tout ce que vous imbriquez entre les balises d’ouverture et de fermeture, ce qui permet aux composants de servir de wrappers composables. Les valeurs par défaut permettent aux appelants d’omettre les props qui restent généralement identiques.
L’état avec useState
Les props sont fixes pour un rendu donné. L’état (state) représente les données dont un composant est propriétaire et qui peuvent évoluer dans le temps. Le hook useState crée une valeur d’état et une fonction de mise à jour (setter).
// Search.jsx
import { useState } from "react";
function Search({ onSearch }) {
const [query, setQuery] = useState("");
return (
<form onSubmit={(e) => { e.preventDefault(); onSearch(query); }}>
<input
value={query}
onChange={(e) => setQuery(e.target.value)}
/>
</form>
);
}
L’appel du setter planifie un nouveau rendu avec la nouvelle valeur. Les mises à jour d’état sont asynchrones et regroupées (batched), et elles remplacent l’état actuel au lieu de le fusionner ; veillez donc à toujours créer un nouvel objet ou un nouveau tableau lors de la mise à jour d’un état structuré.
// update.jsx
setUser((prev) => ({ ...prev, name: "Grace" }));
setItems((prev) => [...prev, newItem]);
L’utilisation de la forme avec fonction de mise à jour (updater function) vous protège lorsque la valeur suivante dépend de la précédente.
Rendu des listes et des conditions
React ne possède pas de langage de template pour les boucles et les branchements — vous utilisez du JavaScript pur.
// List.jsx
function List({ items }) {
if (items.length === 0) return <p>Nothing here yet.</p>;
return (
<ul>
{items.map((item) => (
<li key={item.id}>{item.label}</li>
))}
</ul>
);
}
La prop key est requise pour les éléments d’une liste. Attribuez-lui une valeur stable et unique provenant de vos données afin que React puisse identifier correctement les éléments entre chaque rendu. L’opérateur ternaire et && permettent de gérer les conditions en ligne, bien que les retours anticipés (early returns) soient souvent plus lisibles.
Événements
Les événements React utilisent des props en camelCase et reçoivent un objet d’événement synthétique.
// Button.jsx
<button
onClick={(event) => {
event.preventDefault();
submit();
}}
>
Save
</button>
Il est important de passer une fonction à la prop — onClick={submit()} l’appellerait immédiatement lors du rendu. Lorsqu’un gestionnaire a besoin d’un argument, enveloppez-le dans une fonction fléchée.
Les effets avec useEffect
useEffect synchronise votre composant avec des systèmes externes à React : requêtes réseau, abonnements, timers et manipulations directes du DOM.
// Users.jsx
import { useEffect, useState } from "react";
function Users() {
const [users, setUsers] = useState([]);
useEffect(() => {
const controller = new AbortController();
fetch("/api/users", { signal: controller.signal })
.then((res) => res.json())
.then(setUsers)
.catch((err) => {
if (err.name !== "AbortError") console.error(err);
});
return () => controller.abort();
}, []);
return <ul>{users.map((u) => <li key={u.id}>{u.name}</li>)}</ul>;
}
Le tableau de dépendances contrôle le moment où l’effet est réexécuté : un tableau vide s’exécute une seule fois après le montage, une liste de valeurs s’exécute dès que l’une d’entre elles change, et l’absence de tableau déclenche l’effet après chaque rendu. La fonction retournée sert au nettoyage (cleanup), laquelle s’exécute avant l’effet suivant et lors du démontage. Pensez à toujours nettoyer vos abonnements et vos requêtes en cours.
Context et refs
Le Context permet de partager une valeur avec tout un sous-arbre sans avoir recours au prop drilling.
// theme.jsx
const ThemeContext = createContext("light");
function App() {
return (
<ThemeContext.Provider value="dark">
<Toolbar />
</ThemeContext.Provider>
);
}
function Button() {
const theme = useContext(ThemeContext);
return <button className={theme}>Click</button>;
}
Les Refs conservent une valeur mutable ou un nœud DOM qui ne doit pas déclencher de nouveau rendu.
// focus.jsx
const inputRef = useRef(null);
useEffect(() => inputRef.current?.focus(), []);
return <input ref={inputRef} />;
Flux de données et remontée d’état (lifting state)
Dans React, les données circulent dans une seule direction. Lorsque deux composants frères doivent partager un état, vous devez le remonter (lift) vers leur parent commun le plus proche, puis transmettre la valeur via une prop et la fonction de modification via un callback. Cela permet de maintenir une source unique de vérité et rend le flux de modifications facile à suivre.
Pour des arbres de composants plus profonds, l’utilisation d’un contexte ou d’une bibliothèque de gestion d’état dédiée comme Zustand ou Redux peut justifier l’ajout de cette infrastructure. Ne les utilisez que lorsque le passage de props devient fastidieux, et non avant.
Hooks et hooks personnalisés
Les hooks sont des fonctions qui permettent aux composants d’accéder aux fonctionnalités de React. Ils doivent être appelés au niveau supérieur, jamais à l’intérieur de conditions ou de boucles. Une fois que vous les aurez compris, vous pourrez extraire la logique partagée dans un hook personnalisé.
// useFetch.js
function useFetch(url) {
const [data, setData] = useState(null);
const [error, setError] = useState(null);
useEffect(() => {
let active = true;
fetch(url)
.then((res) => res.json())
.then((json) => active && setData(json))
.catch((err) => active && setError(err));
return () => { active = false; };
}, [url]);
return { data, error };
}
Un hook personnalisé est simplement une fonction dont le nom commence par use et qui appelle d’autres hooks. Il partage la logique, pas l’état — chaque composant qui l’utilise reçoit sa propre copie indépendante.
Bonnes pratiques
- Gardez vos composants petits et concentrés sur une seule responsabilité.
- Calculez les valeurs dérivées pendant le rendu plutôt que de les stocker dans le state.
- Utilisez la forme “updater” d’un setter lorsque la valeur suivante dépend de la précédente.
- Attribuez à chaque élément de liste une clé stable provenant de vos données.
- Nettoyez vos effets, en particulier les abonnements et les requêtes en cours.
- Remontez le state uniquement jusqu’au niveau nécessaire.
- Extrayez la logique répétitive dans des hooks personnalisés.
- Ne recurrez à la mémoïsation (
useMemo,useCallback,memo) qu’après avoir mesuré un problème réel.
Erreurs courantes
- Muter l’état directement au lieu de créer une nouvelle valeur.
- Utiliser l’index du tableau comme clé, ce qui casse le réordonnancement.
- Stocker des données dérivées dans l’état et les synchroniser via un effet.
- Oublier le tableau de dépendances, provoquant ainsi des boucles infinies.
- Appeler un hook de manière conditionnelle, enfreignant ainsi les règles des hooks.
- Optimiser avec la mémoïsation avant même d’avoir un problème de performance.
Et après ?
React est la couche de vue ; Next.js y ajoute le routage, la récupération de données et le rendu côté serveur. Comparez ce modèle avec Vue et Svelte, et renforcez vos bases avec JavaScript et TypeScript. Le tutoriel interactif React reprend ces mêmes concepts étape par étape.