Les modèles mentaux React rendent React simple : apprenez les idées clés derrière composants, rendu, état et effets, puis appliquez-les pour construire des interfaces rapidement via le chat.

React peut sembler frustrant au départ parce que vous voyez l'interface changer, mais vous ne pouvez pas toujours expliquer pourquoi elle a changé. Vous cliquez sur un bouton, quelque chose se met à jour, puis une autre partie de la page vous surprend. Ce n'est généralement pas « React est étrange. » C'est « mon image de ce que React fait est floue. »
Un modèle mental est l'histoire simple que vous vous racontez sur le fonctionnement d'une chose. Si l'histoire est erronée, vous prendrez des décisions confiantes qui mènent à des résultats déroutants. Pensez à un thermostat : un mauvais modèle est « je règle 22°C, donc la pièce devient instantanément 22°C. » Un meilleur modèle est « je règle une cible, et le chauffage s'allume et s'éteint dans le temps pour l'atteindre. » Avec la meilleure histoire, le comportement cesse de sembler aléatoire.
React fonctionne de la même façon. Une fois que vous adoptez quelques idées claires, React devient prévisible : vous pouvez regarder les données courantes et deviner de façon fiable ce qui sera à l'écran.
Dan Abramov a aidé à populariser cet état d'esprit « rendre ça prévisible ». L'objectif n'est pas de mémoriser des règles. C'est de garder un petit ensemble de vérités en tête pour pouvoir déboguer en raisonnant, pas par essai/erreur.
Gardez ces idées en vue :
Accrochez-vous à ça et React cesse de ressembler à de la magie. Il devient un système en lequel vous pouvez avoir confiance.
React devient plus simple quand vous arrêtez de penser en « écrans » et que vous commencez à penser en petites pièces. Un composant est une unité réutilisable d'UI. Il prend des entrées et retourne une description de ce à quoi l'UI doit ressembler pour ces entrées.
Il aide de traiter un composant comme une description pure : « donné ces données, affiche ceci. » Cette description peut être utilisée à plusieurs endroits parce qu'elle ne dépend pas de l'endroit où elle vit.
Les props sont les entrées. Elles viennent d'un composant parent. Les props ne sont pas « possédées » par le composant, et ce n'est pas quelque chose que le composant devrait changer discrètement. Si un bouton reçoit label="Save", le rôle du bouton est d'afficher ce label, pas de décider qu'il devrait être différent.
L'état est des données possédées. C'est ce dont le composant se souvient dans le temps. L'état change quand un utilisateur interagit, quand une requête se termine, ou quand vous décidez que quelque chose doit être différent. Contrairement aux props, l'état appartient à ce composant (ou au composant que vous choisissez pour le posséder).
Version simple de l'idée clé : l'UI est une fonction de l'état. Si l'état dit « loading », affichez un spinner. Si l'état dit « error », affichez un message. Si l'état dit « items = 3 », affichez trois lignes. Votre travail est de garder l'UI lisant depuis l'état, pas de dériver vers des variables cachées.
Une façon rapide de séparer les concepts :
SearchBox, ProfileCard, CheckoutForm)name, price, disabled)isOpen, query, selectedId)Exemple : une modal. Le parent peut passer title et onClose en props. La modal peut posséder isAnimating en état.
Même si vous générez l'UI via un chat (par exemple sur Koder.ai), cette séparation reste la façon la plus rapide de garder la raison : décidez d'abord ce qui est props vs state, puis laissez l'UI suivre.
Une façon utile de tenir React en tête (très dans l'esprit de Dan Abramov) est : le rendu est un calcul, pas un travail de peinture. React exécute vos fonctions de composant pour déterminer à quoi l'UI doit ressembler pour les props et l'état courants. La sortie est une description de l'UI, pas des pixels.
Un rerender signifie simplement que React répète ce calcul. Ça ne veut pas dire « toute la page est redessinée. » React compare le nouveau résultat au précédent et applique le plus petit ensemble de changements au vrai DOM. Beaucoup de composants peuvent rerender tandis que seuls quelques nœuds du DOM sont réellement mis à jour.
La plupart des rerenders se produisent pour quelques raisons simples : l'état d'un composant a changé, ses props ont changé, ou un parent a rerendu et React a demandé à l'enfant de rendre à nouveau. Ce dernier surprend souvent, mais c'est généralement ok. Si vous traitez le render comme « bon marché et ennuyeux », votre app reste plus facile à raisonner.
La règle générale qui garde ça propre : rendez le render pur. Données identiques (props + state) doivent faire que votre composant retourne la même description d'UI. Évitez les surprises dans le render.
Exemple concret : si vous générez un ID avec Math.random() dans le render, un rerender le change et soudain une checkbox perd le focus ou un élément de liste est remonté. Créez l'ID une fois (state, memo, ou en dehors du composant) et le rendu devient stable.
Si vous retenez une phrase : un rerender signifie « recalculer ce que l'UI devrait être », pas « reconstruire tout ».
Un autre modèle utile : les mises à jour d'état sont des demandes, pas des assignations instantanées. Quand vous appelez un setter comme setCount(count + 1), vous demandez à React de planifier un rendu avec une nouvelle valeur. Si vous lisez l'état juste après, vous pouvez voir l'ancienne valeur parce que React n'a pas encore rendu.
C'est pourquoi les mises à jour « petites et prévisibles » comptent. Préférez décrire le changement plutôt que de tenter de saisir ce que vous pensez être la valeur courante. Quand la valeur suivante dépend de la précédente, utilisez la forme updater : setCount(c => c + 1). Ça correspond à la façon dont React fonctionne : plusieurs mises à jour peuvent être mises en file, puis appliquées dans l'ordre.
L'immuabilité est l'autre moitié du tableau. Ne modifiez pas les objets et tableaux en place. Créez-en un nouveau avec la modification. React peut alors voir « cette valeur est nouvelle », et votre cerveau peut tracer ce qui a changé.
Exemple : basculer un todo. L'approche sûre est de créer un nouveau tableau et un nouvel objet todo pour l'élément modifié. L'approche risquée est de faire todo.done = !todo.done dans le tableau existant.
Gardez aussi l'état minimal. Un piège commun est de stocker des valeurs que vous pouvez calculer. Si vous avez déjà items et filter, ne stockez pas filteredItems dans l'état. Calculez-le pendant le render. Moins de variables d'état signifie moins de façons pour les valeurs de diverger.
Un test simple pour ce qui doit être dans l'état :
Si vous construisez l'UI via un chat (y compris sur Koder.ai), demandez des changements comme des petits patchs : « Ajouter un booléen » ou « Mettre à jour cette liste de façon immuable. » Des changements petits et explicites gardent le générateur et votre code React alignés.
Le rendu décrit l'UI. Les effets synchronisent avec le monde extérieur. « Extérieur » signifie les choses que React ne contrôle pas : appels réseau, timers, API du navigateur, et parfois du travail DOM impératif.
Si quelque chose peut être calculé à partir des props et de l'état, ça ne devrait généralement pas vivre dans un effect. Le mettre dans un effect ajoute une étape supplémentaire (render, exécuter l'effect, setState, render à nouveau). Ce saut additionnel est là où apparaissent les scintillements, les boucles, et les bugs du type « pourquoi c'est périmé ? ».
Une confusion courante : vous avez firstName et lastName, et vous stockez fullName dans l'état via un effect. Mais fullName n'est pas un effet secondaire. C'est une donnée dérivée. Calculez-la pendant le render et elle correspondra toujours.
En règle : dérivez les valeurs d'UI pendant le render (ou avec useMemo si c'est vraiment coûteux), et utilisez les effects pour « faire quelque chose », pas pour « déterminer quelque chose ».
Considérez le tableau de dépendances comme : « Quand ces valeurs changent, re-synchronisez avec le monde extérieur. » Ce n'est pas une astuce de performance et ce n'est pas un endroit pour faire taire les warnings.
Exemple : si vous récupérez les détails d'un utilisateur quand userId change, userId appartient au tableau de dépendances parce qu'il doit déclencher la synchronisation. Si l'effect utilise token aussi, incluez-le, sinon vous risquez de fetcher avec un token périmé.
Un bon test intuitif : si supprimer un effect ne ferait que rendre l'UI incorrecte, ce n'était probablement pas un vrai effect. Si le supprimer arrêterait un timer, annulerait un abonnement, ou sauterait un fetch, c'était probablement un effect.
Un des modèles mentaux les plus utiles est simple : les données descendent l'arbre, et les actions utilisateur remontent.
Un parent passe des valeurs aux enfants. Les enfants ne devraient pas « posséder » secrètement la même valeur à deux endroits. Ils demandent des changements en appelant une fonction, et le parent décide de la nouvelle valeur.
Quand deux parties de l'UI doivent être d'accord, choisissez un endroit pour stocker la valeur, puis passez-la vers le bas. C'est le « lifting state ». Ça peut sembler du tuyautage en plus, mais cela prévient un problème pire : deux états qui divergent et vous forcent à ajouter des hacks pour les synchroniser.
Exemple : un champ de recherche et une liste de résultats. Si l'input stocke sa propre query et que la liste stocke sa propre query, vous verrez un jour « l'input montre X mais la liste utilise Y. » La solution est de garder query dans un parent, de la passer aux deux, et de passer un handler onChangeQuery(newValue) à l'input.
Remonter l'état n'est pas toujours la réponse. Si une valeur n'a d'importance que dans un composant, gardez-la là. Garder l'état proche de l'endroit où il est utilisé rend généralement le code plus lisible.
Une frontière pratique :
Si vous hésitez à remonter l'état, cherchez des signes : deux composants affichent la même valeur différemment ; une action à un endroit doit mettre à jour quelque chose loin ; vous copiez des props dans l'état « au cas où » ; ou vous ajoutez des effects seulement pour garder deux valeurs synchrones.
Ce modèle aide aussi quand vous construisez via des outils de chat comme Koder.ai : demandez un seul propriétaire pour chaque morceau d'état partagé, puis générez des handlers qui remontent.
Choisissez une fonctionnalité assez petite pour la garder en tête. Une bonne est une liste consultable où l'on peut cliquer sur un élément pour voir les détails dans une modal.
Commencez par esquisser les parties UI et les événements possibles. Ne pensez pas au code tout de suite. Pensez à ce que l'utilisateur peut faire et voir : il y a un input de recherche, une liste, une mise en surbrillance de la ligne sélectionnée et une modal. Les événements sont taper dans la recherche, cliquer sur un élément, ouvrir la modal et fermer la modal.
Maintenant « dessinez l'état ». Notez les quelques valeurs qui doivent être stockées, et décidez qui les possède. Une règle simple marche bien : le parent commun le plus proche de tous les endroits qui ont besoin d'une valeur devrait la posséder.
Pour cette fonctionnalité, l'état stocké peut être minime : query (string), selectedId (id ou null), et isModalOpen (boolean). La liste lit query et rend les items. La modal lit selectedId pour afficher les détails. Si la liste et la modal ont besoin de selectedId, gardez-le dans le parent, pas dans les deux.
Séparez ensuite les données dérivées des données stockées. La liste filtrée est dérivée : filteredItems = items.filter(...). Ne la stockez pas dans l'état parce qu'elle peut toujours être recalculée depuis items et query. Stocker des données dérivées est la façon dont les valeurs divergent.
Ensuite, demandez : avons-nous besoin d'un effect ? Si les items sont déjà en mémoire, non. Si taper une query doit fetcher des résultats, oui. Si fermer la modal doit sauvegarder quelque chose, oui. Les effects servent à synchroniser (fetch, save, subscribe), pas à relier l'UI basique.
Enfin, testez le flux avec quelques cas limites :
selectedId reste-t-il valide ?Si vous pouvez répondre à ça sur papier, le code React est généralement direct.
La plupart des confusions React ne viennent pas de la syntaxe. Elles surviennent quand votre code cesse de correspondre à l'histoire simple dans votre tête.
Stocker de l'état dérivé. Vous sauvegardez fullName dans l'état alors que c'est juste firstName + lastName. Ça marche jusqu'à ce qu'un champ change et que l'autre ne change pas, et l'UI affiche une valeur périmée.
Boucles d'effets. Un effect fetch des données, setState, et la liste de dépendances le fait rerun encore. Le symptôme est des requêtes répétées, une UI saccadée, ou un état qui ne se stabilise jamais.
Fermetures périmées. Un handler de clic lit une vieille valeur (comme un compteur ou un filtre obsolète). Le symptôme est « j'ai cliqué, mais il a utilisé la valeur d'hier. »
État global partout. Mettre chaque détail UI dans un store global rend difficile de savoir qui possède quoi. Le symptôme est que changer une chose fait réagir trois écrans de façon surprenante.
Mutation d'objets imbriqués. Vous mettez à jour un objet ou un tableau en place et vous vous demandez pourquoi l'UI ne s'est pas mise à jour. Le symptôme est « les données ont changé, mais rien n'a rerendu. »
Voici un exemple concret : un panneau « search and sort » pour une liste. Si vous stockez filteredItems dans l'état, il peut diverger de items quand de nouvelles données arrivent. Au lieu de cela, stockez les entrées (texte de recherche, choix de tri) et calculez la liste filtrée pendant le render.
Avec les effets, gardez-les pour synchroniser avec l'extérieur (fetching, subscriptions, timers). Si un effect fait du travail UI basique, il appartient souvent au render ou à un handler d'événement.
Quand vous générez ou éditez du code via un chat, ces erreurs apparaissent plus vite parce que les changements peuvent arriver en gros morceaux. Une bonne habitude est d'encadrer les requêtes en termes de propriété : « Quelle est la source de vérité pour cette valeur ? » et « Peut-on calculer ceci au lieu de le stocker ? ».
Quand votre UI devient imprévisible, ce n'est rarement « trop de React ». C'est généralement trop d'état, aux mauvais endroits, faisant des jobs qu'il ne devrait pas faire.
Avant d'ajouter un autre useState, faites une pause et demandez :
Exemple simple : search box, dropdown de filtre, liste. Si vous stockez à la fois query et filteredItems dans l'état, vous avez maintenant deux sources de vérité. À la place, gardez query et filter en état, puis dérivez filteredItems pendant le render à partir de la liste complète.
Ceci compte aussi quand vous construisez rapidement via des outils de chat. La vitesse est géniale, mais demandez toujours : « Avons-nous ajouté de l'état, ou avons-nous accidentellement ajouté une valeur dérivée ? » Si c'est dérivé, supprimez cet état et calculez-le.
Une petite équipe construit une UI d'administration : un tableau de commandes, quelques filtres, et un dialogue pour éditer une commande. La première demande est vague : « Ajouter des filtres et une popup d'édition. » Ça paraît simple, mais ça tourne souvent en état aléatoirement dispersé.
Rendez ça concret en traduisant la demande en état et événements. Au lieu de « filtres », nommez l'état : query, status, dateRange. Au lieu de « popup d'édition », nommez l'événement : « l'utilisateur clique sur Edit sur une ligne. » Ensuite décidez qui possède chaque morceau d'état (page, table, ou dialogue) et ce qui peut être dérivé (comme la liste filtrée).
Exemples de prompts qui gardent le modèle intact (fonctionnent bien avec des générateurs comme Koder.ai) :
OrdersPage qui possède filters et selectedOrderId. OrdersTable est contrôlée par filters et appelle onEdit(orderId). »visibleOrders à partir de orders et filters. Ne stockez pas visibleOrders dans l'état. »EditOrderDialog qui reçoit order et open. Quand on sauvegarde, appeler onSave(updatedOrder) et fermer. »filters vers l'URL, pas pour calculer des lignes filtrées. »Après que l'UI est générée ou mise à jour, passez en revue les changements avec un contrôle rapide : chaque valeur d'état a un seul propriétaire, les valeurs dérivées ne sont pas stockées, les effects servent uniquement à synchroniser avec le monde extérieur (URL, réseau, stockage), et les événements descendent en props et remontent en callbacks.
Quand l'état est prévisible, l'itération devient sûre. Vous pouvez changer la mise en page du tableau, ajouter un filtre, ou ajuster les champs du dialogue sans deviner quel état caché va casser ensuite.
La vitesse n'est utile que si l'app reste facile à raisonner. La protection la plus simple est de traiter ces modèles mentaux comme une checklist à appliquer avant d'écrire (ou générer) l'UI.
Commencez chaque fonctionnalité de la même façon : notez l'état nécessaire, les événements qui peuvent le changer, et qui le possède. Si vous ne pouvez pas dire « Ce composant possède cet état, et ces événements le mettent à jour », vous finirez probablement avec un état dispersé et des rerenders surprenants.
Si vous construisez via un chat, commencez en mode planification. Décrivez les composants, la forme de l'état et les transitions en langage simple avant de demander le code. Par exemple : « Un panneau de filtres met à jour l'état query ; la liste de résultats est dérivée de query ; sélectionner un élément définit selectedId ; fermer le modal le réinitialise. » Quand ça se lit clairement, générer l'UI devient mécanique.
Si vous utilisez Koder.ai (koder.ai) pour générer du code React, faites une petite vérification de sanity avant d'aller plus loin : un propriétaire clair pour chaque valeur d'état, UI dérivée de l'état, effects uniquement pour synchroniser, et pas de sources de vérité dupliquées.
Ensuite itérez par petites étapes. Si vous voulez changer la structure d'état (par ex. plusieurs booléens vers un champ status unique), prenez d'abord un snapshot, expérimentez, et revenez en arrière si le modèle mental s'est dégradé. Et quand vous avez besoin d'une revue approfondie ou d'un transfert, exporter le code source facilite la vraie question : la forme de l'état raconte-t-elle toujours l'histoire de l'UI ?
Un bon modèle de départ est : UI = f(state, props). Vos composants ne « modifient pas le DOM » ; ils décrivent ce qui doit être affiché pour les données courantes. Si l’écran est incorrect, inspectez l'état/les props qui l'ont produit, pas le DOM.
Les props sont des entrées depuis un parent ; votre composant doit les traiter comme en lecture seule. L'état est la mémoire possédée par un composant (ou par le composant que vous choisissez comme propriétaire). Si une valeur doit être partagée, remontez-la et passez-la en props.
Un rerender signifie que React réexécute votre fonction de composant pour calculer la prochaine description de l'UI. Ça ne veut pas dire que toute la page est repassée à la peinture. React met ensuite à jour le DOM réel avec le plus petit ensemble de changements nécessaires.
Parce que les mises à jour d'état sont planifiées, pas des assignations immédiates. Si la valeur suivante dépend de l'ancienne, utilisez la forme updater pour ne pas compter sur une valeur possiblement périmée :
setCount(c => c + 1)Ceci reste correct même si plusieurs mises à jour sont en file d'attente.
Évitez de stocker tout ce que vous pouvez calculer à partir des entrées existantes. Stockez les entrées, dérivez le reste pendant le render.
Exemples :
items, filtervisibleItems = items.filter(...)Cela évite que les valeurs divergent.
Utilisez les effects pour synchroniser avec ce que React ne contrôle pas : fetchs, abonnements, timers, API du navigateur, ou travail DOM impératif.
N'utilisez pas un effect juste pour calculer des valeurs d'UI depuis l'état — calculez-les pendant le render (ou avec useMemo si c'est coûteux).
Considérez le tableau de dépendances comme une liste de déclencheurs : « quand ces valeurs changent, re-synchronisez ». Incluez chaque valeur réactive que l'effect lit.
Si vous oubliez quelque chose, vous risquez des données périmées (comme un userId ou un token obsolète). Si vous ajoutez de mauvaises valeurs, vous pouvez créer des boucles — souvent signe que le travail de l'effect appartient plutôt aux handlers ou au render.
Si deux parties de l'UI doivent toujours être d'accord, placez l'état dans leur parent commun le plus proche, passez la valeur vers le bas et les callbacks vers le haut.
Test rapide : si vous dupliquez la même valeur dans deux composants et écrivez des effects pour « les garder synchrones », cet état a probablement besoin d'un seul propriétaire.
C'est généralement dû à un handler qui « capture » une vieille valeur d'une render précédente. Correctifs courants :
setX(prev => ...)Si un clic utilise « la valeur d'hier », suspectez une fermeture périmée.
Commencez par un petit plan : composants, propriétaires d'état et événements. Puis générez du code en petits patches (ajouter un champ d'état, ajouter un handler, dériver une valeur) au lieu de réécritures massives.
Si vous utilisez un générateur comme Koder.ai, demandez :
Cela maintient le code généré aligné avec le modèle mental de React.