React a popularisé l’UI basée sur des composants, le rendu déclaratif et des vues pilotées par l’état — faisant passer les équipes du code centré pages à des systèmes réutilisables et des patterns.

React n’a pas seulement introduit une nouvelle bibliothèque : il a changé ce que les équipes entendent par « architecture frontend ». En pratique, l’architecture frontend regroupe les décisions qui permettent de garder une base de code UI compréhensible à grande échelle : comment vous découpez l’UI en parties, comment les données circulent entre elles, où l’état vit, comment vous gérez les effets secondaires (comme les appels réseau), et comment vous gardez le tout testable et cohérent au sein d’une équipe.
Penser en composants, c’est considérer chaque morceau d’UI comme une petite unité réutilisable qui maîtrise son rendu et peut se composer avec d’autres unités pour construire des pages complètes.
Avant que React ne se popularise, beaucoup de projets étaient organisés autour des pages et de la manipulation du DOM : « trouve cet élément, change son texte, bascule cette classe. » React a poussé les équipes vers un mode par défaut différent :
Ces idées ont modifié le travail quotidien. Les revues de code ont commencé à poser la question « où doit vivre cet état ? » plutôt que « quel sélecteur as-tu utilisé ? » Designers et ingénieurs ont pu s’aligner autour d’un vocabulaire commun de composants, et les équipes ont pu constituer des bibliothèques de blocs UI sans réécrire des pages entières.
Même si une équipe migre plus tard vers un autre framework, beaucoup d’habitudes façonnées par React demeurent : architecture basée sur les composants, rendu déclaratif, flux de données prévisible, et préférence pour des composants de système de design réutilisables plutôt que du code spécifique à une page. React a rendu ces patterns familiers, influençant l’écosystème frontend au sens large.
Avant React, de nombreuses équipes construisaient des interfaces autour des pages, pas d’unités UI réutilisables. Une configuration courante était des templates rendus côté serveur (PHP, Rails, Django, JSP, etc.) qui produisaient du HTML, avec jQuery en complément pour l’interactivité.
On rendait une page, puis on « l’activait » avec des scripts : pickers de date, plugins de modale, validateurs de formulaire, carrousels — chacun avec ses attentes de markup et ses hooks d’événements.
Le code ressemblait souvent à : trouver un nœud DOM, attacher un handler, muter le DOM, et espérer que rien d’autre ne casse. Au fur et à mesure que l’UI grandissait, la « source de vérité » devenait silencieusement le DOM lui-même.
Le comportement UI vivait rarement en un seul endroit. Il était réparti entre :
Un seul widget — par exemple un récapitulatif de panier — pouvait être partiellement construit côté serveur, partiellement mis à jour avec de l’AJAX et partiellement contrôlé par un plugin.
Cette approche fonctionnait pour des améliorations mineures, mais produisait des problèmes récurrents :
Des frameworks comme Backbone, AngularJS et Ember ont tenté d’apporter de la structure avec modèles, vues et routage — souvent une grande amélioration. Mais beaucoup d’équipes misturaient encore des patterns, laissant un besoin d’une manière plus simple de construire des UI en unités répétables.
Le changement le plus important de React se résume simplement et s’avère surprenamment puissant en pratique : l’UI est une fonction de l’état. Plutôt que de traiter le DOM comme « source de vérité » et de le maintenir manuellement synchronisé, on considère les données comme source de vérité et on laisse l’UI être le résultat.
L’état, c’est juste les données dont dépend votre écran : si un menu est ouvert, ce qui est tapé dans un formulaire, quels éléments figurent dans une liste, quel filtre est sélectionné.
Quand l’état change, vous ne parcourez pas la page pour mettre à jour plusieurs nœuds DOM. Vous mettez à jour l’état, et l’UI se rerend pour correspondre.
Le code traditionnel centré DOM finit souvent avec une logique d’update dispersée :
Avec le modèle de React, ces « mises à jour » deviennent des conditions dans votre sortie de rendu. L’écran devient une description lisible de ce qui doit être visible pour un état donné.
function ShoppingList() {
const [items, setItems] = useState([]);
const [text, setText] = useState("");
const add = () => setItems([...items, text.trim()]).then(() => setText(""));
return (
<section>
<form onSubmit={(e) => { e.preventDefault(); add(); }}>
<input value={text} onChange={(e) => setText(e.target.value)} />
<button disabled={!text.trim()}>Add</button>
</form>
{items.length === 0 ? <p>No items yet.</p> : (
<ul>{items.map((x, i) => <li key={i}>{x}</li>)}</ul>
)}
</section>
);
}
Remarquez comment le message d’état vide, l’état désactivé du bouton et le contenu de la liste sont tous dérivés de items et text. C’est la récompense architecturale : la forme des données et la structure de l’UI s’alignent, ce qui rend les écrans plus faciles à comprendre, tester et faire évoluer.
React a fait du « composant » l’unité par défaut du travail UI : une petite pièce réutilisable qui regroupe markup, comportement et accroches de style derrière une interface claire.
Au lieu de disperser templates HTML, listeners et sélecteurs CSS dans des fichiers sans lien, un composant garde les éléments mobiles proches les uns des autres. Cela ne signifie pas que tout doit vivre dans un seul fichier — mais l’organisation se fait autour de ce que l’utilisateur voit et fait, pas autour de l’API DOM.
Un composant pratique inclut généralement :
Le changement important est que vous cessez de penser en termes de « mettre à jour ce div » et commencez à penser en termes de « rendre le Button dans son état désactivé ».
Quand un composant expose un petit ensemble de props (entrées) et d’événements/callbacks (sorties), il devient plus simple de modifier son intérieur sans casser le reste de l’application. Les équipes peuvent se voir attribuer des composants ou dossiers spécifiques (par ex. « UI checkout ») et les améliorer en toute confiance.
L’encapsulation réduit aussi le couplage accidentel : moins de sélecteurs globaux, moins d’effets secondaires inter-fichiers, moins de « pourquoi ce handler de clic a-t-il cessé de fonctionner ? ».
Une fois que les composants deviennent les blocs principaux, le code se met à refléter le produit :
Cette correspondance facilite les discussions UI : designers, PO et ingénieurs parlent des mêmes « choses ».
La pensée composant a poussé beaucoup de bases de code vers une organisation par fonctionnalité ou domaine (par ex. /checkout/components/CheckoutForm) et vers des bibliothèques UI partagées (souvent /ui/Button). Cette structure évolue mieux que des dossiers uniquement centrés pages lorsque les fonctionnalités croissent, et prépare le terrain pour des systèmes de design.
Le style de rendu de React est souvent décrit comme déclaratif : vous décrivez à quoi doit ressembler l’UI pour une situation donnée, et React s’occupe de faire correspondre le navigateur.
Dans les approches antérieures, on écrivait des instructions étape par étape :
Avec le rendu déclaratif, on exprime le résultat :
Si l’utilisateur est connecté, afficher son nom. Sinon, afficher un bouton « Se connecter ».
Ce changement réduit la quantité de « gestion UI » à tenir en tête. Vous ne suivez pas constamment quels éléments existent et ce qu’il faut mettre à jour : vous vous concentrez sur les états possibles de l’application.
JSX est une manière pratique d’écrire la structure UI proche de la logique qui la contrôle. Plutôt que de séparer templates et logique et sauter entre eux, vous gardez les pièces liées ensemble : la structure ressemblant à du markup, les conditions, de petits formats et les handlers.
Cette collocation est une grande raison pour laquelle le modèle de composant de React a paru pratique. Un composant n’est pas juste un bout de HTML ni un paquet de JS : c’est une unité de comportement UI.
Une inquiétude fréquente est que JSX mélange HTML et JS, ce qui paraît un recul. Mais JSX n’est pas vraiment du HTML : c’est une syntaxe qui produit des appels JavaScript. Plus important, React ne mélange pas tant les technologies que les choses qui changent ensemble.
Quand la logique et la structure UI sont liées (par ex. « afficher un message d’erreur seulement quand la validation échoue »), les garder au même endroit peut être plus clair que de disperser des règles dans des fichiers séparés.
JSX a rendu React accessible, mais le concept sous-jacent va au-delà. Vous pouvez écrire React sans JSX, et d’autres frameworks utilisent aussi le rendu déclaratif avec d’autres syntaxes. L’impact durable est l’état d’esprit : traiter l’UI comme une fonction de l’état et laisser le framework gérer la mécanique de synchronisation de l’écran.
Avant React, une source fréquente de bugs était simple : les données changeaient, mais l’UI non. Les développeurs allaient chercher de nouvelles données, puis trouvaient manuellement les bons nœuds DOM, mettaient à jour du texte, basculaient des classes, ajoutaient/supprimaient des éléments, et devaient garder tout cela cohérent. Avec le temps, la logique d’update devenait souvent plus complexe que l’UI elle-même.
Le grand changement de workflow de React est que vous n’« ordonnez » pas au navigateur comment changer la page. Vous décrivez ce que l’UI doit être pour un état donné, et React se charge de mettre le DOM réel à jour pour correspondre.
La réconciliation est le processus par lequel React compare ce que vous avez rendu précédemment et ce que vous rendez maintenant, puis applique l’ensemble minimal de changements au DOM du navigateur.
L’important n’est pas que React utilise un « DOM virtuel » comme un tour de passe-passe pour la performance. C’est que React vous donne un modèle prévisible :
Cette prévisibilité améliore le flux de travail du développeur : moins de mises à jour manuelles du DOM, moins d’états incohérents, et des mises à jour UI qui suivent les mêmes règles partout.
Lors du rendu de listes, React a besoin d’une façon stable d’apparier les « anciens éléments » aux « nouveaux éléments » pendant la réconciliation. C’est l’objet de key.
{todos.map(todo => (
<TodoItem key={todo.id} todo={todo} />
))}
Utilisez des clés stables et uniques (comme un ID). Évitez les index de tableau si les éléments peuvent être réordonnés, insérés ou supprimés — sinon React peut réutiliser la mauvaise instance de composant et provoquer des comportements surprenants (par ex. des champs qui conservent une mauvaise valeur).
L’un des grands changements architecturaux de React est que les données circulent dans une seule direction : des composants parents vers les enfants. Plutôt que de permettre à n’importe quelle partie de l’UI de « pénétrer » d’autres parties et de muter un état partagé, React vous encourage à traiter les mises à jour comme des événements explicites qui montent, tandis que les données résultantes descendent.
Un parent possède l’état et le passe au child via des props. Le child peut demander une modification en appelant un callback.
function Parent() {
const [count, setCount] = React.useState(0);
return (
<Counter
value={count}
onIncrement={() => setCount(c => c + 1)}
/>
);
}
function Counter({ value, onIncrement }) {
return (
<button onClick={onIncrement}>
Clicks: {value}
</button>
);
}
Remarquez ce qui ne se produit pas : le Counter ne modifie pas count directement. Il reçoit value (les données) et onIncrement (un moyen de demander un changement). Cette séparation est au cœur du modèle mental.
Ce pattern rend les frontières évidentes : « qui possède ces données ? » se répond souvent par « le parent commun le plus proche ». Quand quelque chose change de manière inattendue, on remonte au composant où l’état est géré — pas à une toile de mutations cachées.
Cette distinction aide les équipes à décider où placer la logique et évite le couplage accidentel.
Les composants qui reposent sur des props sont plus simples à réutiliser car ils ne dépendent pas de variables globales ou de requêtes DOM. Ils sont aussi plus faciles à tester : vous pouvez les rendre avec des props spécifiques et vérifier la sortie, tandis que le comportement avec état est testé là où l’état est géré.
React a poussé les équipes à laisser tomber les hiérarchies de classes pour l’UI et à assembler des écrans à partir de petites pièces ciblées. Au lieu d’étendre une Button de base en dix variantes, on compose comportement et visuel en combinant des composants.
Un pattern courant est de créer des composants de layout qui ne connaissent rien des données qu’ils contiendront :
PageShell pour header/sidebar/footerStack / Grid pour espacement et alignementCard pour encadrement cohérentCes composants acceptent children pour que la page décide de ce qu’elle met dedans, pas le layout.
Vous verrez aussi des wrappers légers comme RequireAuth ou ErrorBoundary qui ajoutent une préoccupation autour de ce qu’ils enveloppent, sans modifier l’intérieur du composant enveloppé.
Quand on a besoin de plus de contrôle que children, les équipes utilisent souvent une approche de type « slot » via des props :
Modal avec title, footer et childrenTable avec renderRow ou emptyStateCela garde les composants flexibles sans exploser l’API.
Les arbres d’héritage profonds commencent souvent avec de bonnes intentions (« on réutilisera la classe de base »), mais deviennent difficiles à gérer car :
Les hooks ont rendu la composition encore plus pratique. Un hook personnalisé comme useDebouncedValue ou usePermissions permet à plusieurs composants fonctionnels de partager de la logique sans partager de UI. Associez cela à des primitives UI partagées (boutons, champs, typographie) et à des composants de fonctionnalité (CheckoutSummary, InviteUserForm) pour obtenir de la réutilisation lisible à mesure que l’application grandit.
React a rendu naturel de commencer par de l’état local : valeur d’un champ, menu ouvert, spinner. Ça marche bien — jusqu’à ce que l’application grandisse et que plusieurs parties de l’UI doivent rester synchrones.
Au fur et à mesure que les fonctionnalités s’étendent, l’état doit souvent être lu ou mis à jour par des composants qui ne sont pas en relation parent-enfant. « Il suffit de passer des props » se transforme en longues chaînes de props traversant des composants qui s’en fichent, augmentant le boilerplate et le risque de bugs où deux endroits représentent « le même » état.
lift state up)Monter l’état vers le parent commun le plus proche et le passer en props. C’est souvent la solution la plus simple, mais elle peut créer des « god components » si on en abuse.
React Context aide quand beaucoup de composants ont besoin de la même valeur (thème, locale, utilisateur courant). Il réduit le prop drilling, mais si vous stockez des données qui changent fréquemment dans le context, il peut devenir plus difficile de raisonner sur les mises à jour et sur les performances.
Pour les grandes applications, l’écosystème a répondu avec des bibliothèques comme Redux et d’autres patterns de store. Elles centralisent les mises à jour d’état, souvent avec des conventions autour d’actions et de sélecteurs, ce qui peut améliorer la prévisibilité à grande échelle.
Privilégiez l’état local par défaut, remontez l’état quand des éléments frères doivent se coordonner, utilisez le context pour les préoccupations transverses, et envisagez un store externe quand de nombreux composants distants dépendent des mêmes données et que l’équipe a besoin de règles plus strictes pour les mises à jour. Le « bon » choix dépend moins des tendances que de la complexité de l’app, de la taille de l’équipe et de la fréquence des changements de requirement.
React n’a pas seulement introduit une nouvelle manière d’écrire des UI : il a poussé les équipes vers un workflow centré composants où code, style et comportement sont développés comme de petites unités testables. Ce changement a influencé la façon dont les projets frontend sont construits, validés, documentés et livrés.
Quand l’UI est composée de composants, il devient naturel de travailler « des bords vers l’intérieur » : construire un bouton, puis un formulaire, puis une page. Les équipes ont commencé à traiter les composants comme des produits avec des API claires (props), des états prévisibles (loading, empty, error) et des règles de style réutilisables.
Changement concret : designers et développeurs peuvent s’aligner autour d’un inventaire de composants, réviser le comportement isolément et réduire les surprises de dernière minute au niveau page.
La popularité de React a aidé à standardiser une chaîne d’outils moderne que beaucoup d’équipes jugent aujourd’hui indispensable :
Même si vous ne choisissez pas les mêmes outils, l’attente reste : une app React doit avoir des garde-fous qui attrapent les régressions UI tôt.
Comme extension plus récente de cet état d’esprit axé workflow, certaines équipes utilisent des plateformes de génération assistée comme Koder.ai pour esquisser des frontends React (et le backend qui les entoure) depuis un flux de planification conversationnel — utile pour valider rapidement la structure des composants, la propriété de l’état et les limites de fonctionnalités avant de passer des semaines sur l’infrastructure manuelle.
Les équipes React ont aussi popularisé l’idée d’un explorateur de composants : un environnement dédié où l’on rend les composants dans différents états, ajoute des notes et partage une source unique de vérité pour les usages.
Cette pensée à la Storybook change la collaboration : on peut réviser le comportement d’un composant avant qu’il soit intégré à une page et valider délibérément les cas limites plutôt que d’espérer qu’ils surviennent lors d’une QA manuelle.
Si vous construisez une bibliothèque réutilisable, cela se marie naturellement avec une approche de système de design — voir /blog/design-systems-basics.
La boîte à outils centrée composants favorise des PR plus petites, une revue visuelle plus claire et des refactors plus sûrs. Avec le temps, les équipes livrent plus vite car elles itèrent sur des pièces bien délimitées plutôt que de naviguer dans un code DOM enchevêtré.
Concrètement, un système de design combine deux choses : une bibliothèque de composants UI réutilisables (boutons, formulaires, modales, navigation) et des guidelines expliquant comment et quand les utiliser (espacements, typographie, ton, règles d’accessibilité, patterns d’interaction).
React a rendu cette approche naturelle parce que « composant » est déjà l’unité centrale. Plutôt que de copier du markup entre pages, les équipes peuvent publier un \u003cButton />, \u003cTextField /> ou \u003cDialog /> une fois et le réutiliser partout — tout en permettant une personnalisation contrôlée via des props.
Les composants React sont autonomes : ils peuvent encapsuler structure, comportement et style derrière une interface stable. Cela facilite la création d’une bibliothèque qui soit :
Si vous démarrez, une checklist simple aide à empêcher qu’une « pile de composants » ne devienne un bazar incohérent : /blog/component-library-checklist.
Un système de design n’est pas que visuel : c’est aussi comportemental. Quand une modale gère toujours correctement le focus ou qu’un dropdown prend toujours en charge la navigation au clavier, l’accessibilité devient la norme plutôt qu’un ajout.
Le theming s’en trouve facilité : centralisez les tokens (couleurs, espaces, typographie) et laissez les composants les consommer pour que les changements de marque n’exigent pas de toucher chaque écran.
Pour une équipe qui évalue l’effort d’investir dans des composants partagés, la décision se relie souvent à l’échelle et aux coûts de maintenance ; certaines organisations l’intègrent à des plans plateforme comme /pricing.
React n’a pas seulement changé la façon de construire des UI : il a modifié la manière dont on évalue la qualité. Quand votre application est composée de composants avec des entrées claires (props) et des sorties (UI rendue), les tests et la performance deviennent des décisions architecturales, pas des correctifs de dernière minute.
Les frontières de composants permettent de tester à deux niveaux utiles :
Cela fonctionne mieux quand les composants ont une propriété claire : un endroit qui possède l’état, et des enfants qui affichent principalement des données et émettent des événements.
Les apps React semblent souvent rapides parce que les équipes intègrent la performance dans la structure :
Règle utile : optimisez les parties « coûteuses » — longues listes, calculs complexes, zones fréquemment rerendues — plutôt que de courir après des gains minuscules.
Avec le temps, les équipes peuvent dériver vers des pièges courants : trop décomposer en composants (trop de petites pièces sans but clair), prop drilling (transmission de props sur de nombreuses couches) et frontières floues où personne ne sait quel composant possède un état.
Quand on va vite (surtout avec du code auto-généré ou scaffoldé), ces pièges apparaissent plus vite : les composants se multiplient et la propriété devient floue. Que vous codiez à la main ou utilisiez un outil comme Koder.ai pour générer une app React plus backend (souvent Go avec PostgreSQL), les garde-fous sont les mêmes : explicitez la propriété de l’état, gardez les API de composants petites et refactorez vers des frontières fonctionnelles claires.
Server Components, méta-frameworks et de meilleurs outils continueront d’évoluer la livraison des apps React. La leçon durable reste : concevez autour de l’état, de la propriété et de blocs UI composables, puis laissez les tests et la performance suivre naturellement.
Pour des décisions de structure plus approfondies, voir /blog/state-management-react.
React a recentré l’architecture frontend autour de quelques décisions clés :
L’effet pratique : moins de gestion manuelle du DOM et des frontières plus claires pour les équipes et les outils.
La pensée composant consiste à considérer chaque partie de l’interface comme une petite unité réutilisable qui gère son rendu et peut être assemblée dans des écrans plus larges. Concrètement, un composant regroupe :
Cela fait passer la logique de « mettre à jour ce nœud DOM » à « rendre ce composant pour cet état ».
Dans une approche centrée DOM, le DOM finit souvent par devenir la source de vérité, et vous devez synchroniser manuellement plusieurs éléments. Avec React, vous modifiez l’état et le rendu s’ajuste en conséquence : les conditions comme les spinners de chargement, les boutons désactivés et les états vides restent cohérents par construction.
Bon test : si vous écrivez beaucoup d’étapes « trouver un élément et basculer une classe », vous luttez contre le modèle ; si l’UI « se décale », c’est généralement un problème de propriété d’état.
Avant React, de nombreuses applications étaient centrées sur les pages : templates serveur, jQuery et plugins. Le comportement était réparti entre vues serveur, attributs HTML et initialisateurs JS.
Problèmes fréquents :
React a poussé vers des composants réutilisables et des mises à jour prévisibles.
Le rendu déclaratif consiste à décrire ce à quoi l’UI doit ressembler pour un état donné, plutôt que comment muter le DOM étape par étape.
Au lieu de :
Vous exprimez les conditions dans le rendu (par exemple « si connecté afficher le nom, sinon afficher le bouton ‘Se connecter’ ») et React se charge de mettre à jour le DOM réel.
JSX a rendu pratique la collocation de la structure UI et de la logique qui la contrôle (conditions, formats, handlers). Cela réduit les allers-retours entre fichiers de template et fichiers de logique.
JSX n’est pas du HTML : il compile en JavaScript. Le bénéfice principal est organisationnel : regrouper ce qui change ensemble (UI + comportement) dans un même composant facilite la maintenance.
La réconciliation est le processus par lequel React compare le rendu précédent et le rendu actuel, puis applique l’ensemble minimal de modifications au DOM.
L’intérêt pratique est la prévisibilité : vous écrivez le rendu comme si vous reconstruisiez l’UI, et React applique des mises à jour incrémentales.
Pour les listes, utilisez des key stables et uniques (par exemple des identifiants). Évitez les indexes de tableau quand les éléments peuvent être insérés/réordonnés, sinon React peut réutiliser la mauvaise instance de composant (par ex. des champs qui conservent une valeur incorrecte).
Le flux de données unidirectionnel signifie que les données descendent des parents vers les enfants via des props, et que les enfants demandent des changements via des callbacks.
Cela clarifie les responsabilités :
Pour déboguer, on cherche d’abord l’endroit où l’état vit plutôt que de traquer des mutations cachées dans tout le code.
La composition consiste à assembler des comportements en combinant des composants plutôt qu’en étendant des classes.
Patrons courants :
Progression pratique :
lift state up) quand des frères doivent se synchroniserchildren (PageShell, Grid, Card)RequireAuth, ErrorBoundary)title, footer, renderRow, emptyState) quand children ne suffit pasCela reste flexible sans les effets de bord des hiérarchies d’héritage profondes.
Choisissez selon la complexité de l’application et les besoins de l’équipe, pas selon la mode.