Repenser l’état de React : où vos données devraient réellement se trouver
Moins de bugs React grâce à une utilisation réduite de useState : placez l’état dans l’URL, le DOM ou des valeurs dérivées, et déterminez qui est responsable de chaque élément avant de recourir à une gestion d’état.
Sources: Stop Adding React State: It’s Creating Bugs You Don’t Need
Un représentant des ventes dans une entreprise SaaS en pleine croissance passe une bonne partie de la matinée à parcourir une base de données clients contenant dix mille comptes.
Après un filtrage minutieux, il isole les clients entreprises basés en Europe dont les abonnements n’ont pas été renouvelés au cours des derniers quatre-vingt-dix jours.
Le résultat est une liste précise de trente comptes nécessitant une attention immédiate.
Il copie directement l’URL depuis le navigateur et la envoie par Slack à son directeur régional, accompagnée d’une note :
">Ce sont les comptes prioritaires pour ce matin."
Le directeur ouvre le lien.
La page s’affiche.
Mais au lieu de la liste filtrée, on y voit l’affichage par défaut : tous les dix mille comptes, non filtrés et non triés.
Tout ce filtrage méticuleux a disparu parce que l’ingénieur qui avait conçu la page avait stocké chaque filtre, champ de tri et valeur de pagination dans l’état du composant local à l’aide de useState.
Ce scénario illustre un schéma qui apparaît constamment dans les bases de code React.
Nous avons tendance à recourir à l’état simplement parce que React le rend si facile à créer.
Avez-vous besoin d’une valeur de filtre ?
useState.
Avez-vous besoin de suivre quel onglet est actif ?
useState.
Avez-vous besoin d’un compteur ?
useState.
Avez-vous besoin de conserver un champ de formulaire ?
useState.
Avez-vous besoin de suivre les différentes phases d’une appel API ?
Cela représente encore trois appels à useState.
Bientôt, un seul composant gère des dizaines de valeurs qui n’avaient en réalité jamais eu besoin d’exister dans l’état React à l’origine.
Le state en soi n’est pas l’ennemi ici. Chaque application React non triviale en a besoin.
Le véritable problème réside dans le placement du state là où il ne devrait pas être.
Chaque variable de state supplémentaire représente une chose de plus que votre application doit synchroniser avec tout le reste.
Si cela n’est pas contrôlé, cela entraîne toute une série de problèmes, parmi lesquels :
- Un travail supplémentaire pour maintenir les valeurs dupliquées en accord
- Des données devenues obsolètes dans un cache quelque part
- Des valeurs affichées à l’écran qui ne correspondent plus à la réalité
- Des mises à jour qui se déclenchent alors qu’aucun changement significatif n’a eu lieu
- Des bugs de synchronisation où deux mises à jour entrent en conflit de manière imprévisible
- Des effets de rendu qui deviennent de plus en plus complexes pour maintenir la cohérence
- Des bugs dont il faut beaucoup plus de temps pour retrouver l’origine
- Une page qui oublie tout dès qu’elle est rechargée
Rédiger du React de qualité ne consiste pas vraiment à maîtriser une logique d’état complexe.
Souvent, il s’agit de savoir quand ne pas créer cet état du tout.
1. L’URL est le meilleur gestionnaire d’état de votre application
Imaginez un écran typique d’une application riche en données.
Il doit probablement suivre :
- Recherche
- Filtres
- Mise en ordre
- Pagination
- Onglets actifs
- Catégories sélectionnées
- Rangées de dates
L’approche habituelle consiste à stocker tout cela dans l’état du composant.
function ProductList() {
const [activeCategory, setActiveCategory] = useState('all');
const [currentPage, setCurrentPage] = useState(1);
const [searchQuery, setSearchQuery] = useState('');
// Fetch and filter data...
}
À première vue, cela semble parfaitement correct.
Puis l’utilisateur appuie sur « actualiser ».
Toute valeur revient à sa valeur par défaut.
Ou bien ils partagent le lien avec un collègue.
Ce collègue se retrouve sur une vue complètement différente.
Ou bien ils cliquent sur le bouton Retour du navigateur.
Le filtrage qu’ils avaient configuré peut ne pas être réactivé, car l’état de React n’a aucune connexion intégrée avec l’historique de navigation du navigateur.
useState lui-même n’est pas en cause ici.
Le véritable problème est que l’URL existe déjà comme mécanisme pour représenter l’état de navigation, et elle est complètement contournée.
Au lieu d’écrire :
const [currentPage, setCurrentPage] = useState(1);
const [searchQuery, setSearchQuery] = useState('');
const [category, setCategory] = useState('all');
on pourrait encoder les mêmes informations directement dans l’URL.
Quelque chose comme :
/products?category=enterprise&page=3&query=react
En utilisant une bibliothèque de routage comme Next.js, React Router ou TanStack Router, on peut lire ces paramètres directement depuis l’URL :
import { useSearchParams } from 'next/navigation';
function ProductList() {
const searchParams = useSearchParams(); const category = searchParams.get('category') || 'all';
const page = Number(searchParams.get('page')) || 1;
const query = searchParams.get('query') || ''; // Fetch data using the URL state...
}
Ce petit changement modifie considérablement le cycle de vie de cet état.
Rafraîchir la page ?
Les filtres restent inchangés.
Partager le lien ?
Tout utilisateur qui l’ouvre verra exactement la même vue.
Le sauvegarder en favori ?
Il rechargera ultérieurement dans cet état exact.
Appuyer sur « Retourner en arrière » ?
Le navigateur parcourt correctement les états précédents.
C’est là une véritable avance architecturale.
L’état de l’URL vous offre plus que simplement la persistance
Résister à un rafraîchissement de page n’est qu’une partie des avantages.
L’avantage majeur est que l’URL devient un instantané portable de l’état actuel de votre application, pouvant être partagé avec n’importe qui.
Prenons par exemple un tableau de bord de support client :
/support/tickets?status=open&priority=high&team=billing
Un manager peut envoyer ce lien exact à un autre manager en un instant.
Un tableau de bord axé sur les ventes pourrait ressembler à ceci :
/accounts?region=europe&plan=enterprise&renewal=90
Un outil d’analyse pourrait utiliser quelque chose comme ceci :
/analytics?range=30d&metric=revenue&groupBy=region
Aucune de ces chaînes de requête n’est arbitraire.
Chacune d’elles représente un lien ciblé menant à un état spécifique et reconstituable de l’application.
C’est précisément à cela que servent les URL.
Lorsque l’état URL est pertinent
Les paramètres URL s’avèrent très utiles pour des éléments tels que :
- Ce que l’utilisateur a saisi dans la barre de recherche
- Les filtres actifs sélectionnés
- La colonne et la direction selon lesquelles les données sont triées
- La page des résultats affichée
- L’onglet actuellement sélectionné
- Une plage de dates choisie
- Vue enregistrée actuellement ouverte
- Paramètres d’un rapport généré
- Configuration personnalisée sur un tableau de bord
- Tout état de l’interface que l’utilisateur souhaite transmettre à quelqu’un d’autre
Néanmoins, tout ne convient pas pour y être inclus.
Les mots de passe ne doivent évidemment pas figurer dans l’URL.
Même un état d’animation modale éphémère ne devrait pas l’être.
Généralement parlant, un objet volumineux et profondément imbriqué non plus.
La question clé est simple :
Demandez-vous si un utilisateur s’attendrait raisonnablement à ce que cette vue puisse être partagée, enregistrée dans les favoris ou restaurée — si c’est le cas, l’URL est probablement l’endroit approprié pour cet état.
2. Cessez de stocker des valeurs que vous pouvez simplement calculer
Une façon rapide d’alléger l’état de React consiste à cesser de conserver des valeurs qui proviennent en réalité d’autres valeurs.
Prenons cet exemple :
const [items, setItems] = useState([]);
const [itemCount, setItemCount] = useState(0);
Et ailleurs dans le composant :
setItems(newItems);
setItemCount(newItems.length);
Vous disposez maintenant de deux variables d’état distinctes décrivant la même réalité sous-jacente.
Si items est mis à jour mais que itemCount ne le suit pas, votre interface affichera des informations inexactes.
Une version plus propre ressemble à ceci :
const [items, setItems] = useState([]);
const itemCount = items.length;
Il existe maintenant une seule source de vérité.
Le comptage est calculé chaque fois que le composant s’affiche.
La même logique s’applique lors du filtrage des collections.
Au lieu d’écrire :
const [items, setItems] = useState([]);
const [activeItems, setActiveItems] = useState([]);
on peut généralement simplement écrire :
const activeItems = items.filter(item => item.active);
Ou bien :
const totalPrice = items.reduce(
(total, item) => total + item.price,
0
);
Ou encore :
const hasErrors = fields.some(field => field.error);
Ou bien :
const completedCount = todos.filter(todo => todo.completed).length;
La question à se poser n’est pas :
"Puis-je techniquement stocker cela dans l’état ?"
Bien sûr, vous le pouvez.
La question à se poser en réalité est :
"Ce valeur a-t-elle son propre cycle de vie distinct ?"
Si ce n’est pas le cas, elle ne devrait probablement pas faire partie de l’état.
3. Cessez de relier chaque champ de formulaire à un état
Une autre habitude à abandonner consiste à traiter chaque champ de formulaire comme une variable d’état indépendante.
function ContactForm() {
const [firstName, setFirstName] = useState('');
const [lastName, setLastName] = useState('');
const [email, setEmail] = useState('');
const [message, setMessage] = useState('');
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault(); submitData({
firstName,
lastName,
email,
message
});
}; return (
<form onSubmit={handleSubmit}>
<input
value={firstName}
onChange={e => setFirstName(e.target.value)}
/> <input
value={lastName}
onChange={e => setLastName(e.target.value)}
/> <input
value={email}
onChange={e => setEmail(e.target.value)}
/> <textarea
value={message}
onChange={e => setMessage(e.target.value)}
/> <button type="submit">Send</button>
</form>
);
}
Rien ici n’est techniquement incorrect.
Les entrées contrôlées sont utiles lorsque votre application a réellement besoin de réagir au fur et à mesure que l’utilisateur tape. Voici quelques situations où cela est important :
- Vérifier la validité d’un champ au fur et à mesure de sa saisie
- Fournir des suggestions en mode complétion automatique
- Réformater du texte en temps réel
- Compter le nombre de caractères restants
- Afficher ou cacher d’autres champs en fonction des entrées
- Évaluer la force d’un mot de passe
- Lier le comportement d’un champ à la valeur d’un autre
Mais souvent, votre application n’a aucune raison de se soucier de ce que l’utilisateur a tapé avant qu’il n’appuie sur Envoyer.
Dans de tels cas, il n’est pas nécessaire que React suive chaque caractère au fur et à mesure de sa saisie.
Le navigateur s’occupe déjà de cette tâche.
Laissez le navigateur s’en charger
Les formulaires HTML natifs gèrent les valeurs saisies depuis des décennies.
FormData :
function ContactForm() {
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
const formData = new FormData(e.currentTarget); const payload = {
firstName: formData.get('firstName') as string,
lastName: formData.get('lastName') as string,
email: formData.get('email') as string,
message: formData.get('message') as string,
}; submitData(payload);
}; return (
<form onSubmit={handleSubmit}>
<input name="firstName" required />
<input name="lastName" required />
<input name="email" type="email" required />
<textarea name="message" required /> <button type="submit">Send</button>
</form>
);
}
Avec ce modèle, React n’a plus besoin d’une variable d’état dédiée pour chaque champ.
Le navigateur conserve ce que l’utilisateur a saisi.
React lit simplement les valeurs une fois le formulaire soumis.
Cela devient particulièrement utile pour les formulaires volumineux.
Imaginez un processus d’onboarding pour une entreprise comportant 30 champs.
Voudriez-vous vraiment 30 variables d’état distinctes rien que pour conserver ce que quelqu’un a tapé ?
Probablement pas.
Les entrées contrôlées et non contrôlées peuvent coexister
Tout cela ne signifie pas pour autant que les composants contrôlés sont une erreur.
Ils ne le sont pas.
Il existe de nombreuses situations où il est tout à fait approprié de contrôler les entrées.
L’idée est simplement d’abandonner l’hypothèse selon laquelle React doit par défaut gérer la valeur de chaque champ.
Si votre application n’a pas besoin des données avant soumission, il suffit souvent de laisser le formulaire natif les conserver.
Faire cette distinction peut considérablement simplifier les formulaires complexes.
4. Pourquoi les flags booléens échouent
Un autre problème récurrent apparaît constamment dans les bases de code du monde réel.
Prenons un appel API typique.
Un schéma courant consiste à le suivre avec trois booléens distincts :
const [isLoading, setIsLoading] = useState(false);
const [isSuccess, setIsSuccess] = useState(false);
const [isError, setIsError] = useState(false);
Au début, les trois sont faux :
loading = false
success = false
error = false
Lorsque la requête commence :
loading = true
Lorsqu’elle se termine avec succès :
loading = false
success = true
Cela semble raisonnable à première vue.
Mais supposons qu’une branche de gestion des erreurs échoue à réinitialiser isLoading.
loading = true
error = true
Ou un mécanisme de tentative mal conçu pourrait vous laisser avec :
success = true
error = true
À ce stade, votre composant se trouve dans un état qui n’a pas de sens logique.
Faut-il qu’il affiche le message de succès ?
Faut-il qu’il affiche l’état d’erreur ?
Faut-il toujours afficher un indicateur de chargement ?
Techniquement, les trois valeurs booléennes pourraient justifier une réponse « oui » en même temps.
Cette ambiguïté est précisément le bug.
Traitez-le plutôt comme une machine à états finis
Une approche plus claire :
type RequestStatus =
| 'idle'
| 'loading'
| 'success'
| 'error';
const [status, setStatus] =
useState<RequestStatus>('idle');
Désormais, chaque état valide est explicite et mutuellement exclusif.
La requête ne peut être qu’un des suivants :
idle
loading
success
error
Il n’y a aucun risque d’afficher par erreur à la fois « en chargement » et « réussi ».
Le rendu devient également beaucoup plus facile à suivre :
if (status === 'loading') {
return <Spinner />;
}
if (status === 'error') {
return <ErrorMessage />;
}if (status === 'success') {
return <SuccessBanner />;
}return <DefaultForm />;
Ce n’est pas simplement un avantage supplémentaire de TypeScript.
Cela reflète une règle de conception plus large :
Lorsque deux états ne peuvent jamais être vrais indépendamment l’un de l’autre, ils ne devraient pas être modélisés comme deux variables distinctes.
5. Éviter d’utiliser des effets pour synchroniser l’état
C’est encore un cas où des variables d’état supplémentaires génèrent du code inutile et évitable.
Prenons cette configuration :
const [firstName, setFirstName] = useState('');
const [lastName, setLastName] = useState('');
const [fullName, setFullName] = useState('');
En combinaison avec :
useEffect(() => {
setFullName(`${firstName} ${lastName}`);
}, [firstName, lastName]);
Ce que vous avez construit ici est un mécanisme de synchronisation pour une valeur qui n’avait jamais eu besoin d’un état propre à l’origine.
La solution plus simple :
const fullName = `${firstName} ${lastName}`;
Le changement peut sembler mineur, mais son impact architectural est significatif.
La version originale nécessite :
- Trois variables d’état distinctes
La version révisée n’a besoin que de :
- Deux valeurs réelles
- Une valeur dérivée d’elles
- Aucun effet
- Aucune logique de synchronisation à maintenir
Une bonne habitude lors de la révision des composants React est de se demander :
"Pourquoi cette valeur doit-elle exister en dehors du calcul de rendu ?"
Si la réponse honnête est "pour rester synchronisée avec autre chose," c’est généralement un signe que cette valeur ne devrait pas être du tout un état.
6. Trois questions à se poser avant d’ajouter un état
const [value, setValue] = useState(...);
effectuez d’abord trois vérifications.
Question 1 : Peut-on le calculer pendant le rendu ?
Si les données nécessaires pour générer cette valeur existent déjà, il n’y a aucune raison de stocker une copie supplémentaire.
Au lieu de :
const [itemCount, setItemCount] = useState(0);
écrire :
const itemCount = items.length;
Au lieu de :
const [hasErrors, setHasErrors] = useState(false);
écrire :
const hasErrors = fields.some(field => field.error);
Évitez de conserver l’état pour tout ce qui peut être déduit sur place.
Question 2 : Cet état doit-il survivre à un rechargement de page ?
Si c’est le cas, réfléchissez au fait de savoir si l’URL est le bon conteneur pour ces données.
Candidats typiques :
- Mots-clés de recherche
- État de pagination
- Filtres actifs
- Ordre de tri
- Onglets sélectionnés
- Rangées de dates
Demandez-vous : si un lien vers cette page est partagé, le destinataire doit-il arriver exactement sur la même vue ?
Si oui, l’URL est généralement le meilleur endroit pour stocker ces données.
Question 3 : Le navigateur peut-il conserver ces données jusqu’à la soumission du formulaire ?
Si la valeur d’un champ n’a d’importance qu’au moment de la soumission, une entrée non contrôlée peut suffire.
Au lieu de :
const [email, setEmail] = useState('');
vous n’aurez peut-être besoin que de :
<input name="email" type="email" />
et de la lire plus tard avec :
const formData = new FormData(e.currentTarget);
Laissez le navigateur gérer ce qu’il est déjà conçu pour gérer.
7. Ce qui appartient véritablement à l’état React
Rien de tout cela ne justifie l’élimination complète de l’état des composants.
Tenter de l’éliminer entièrement reviendrait à aller trop loin dans la correction.
De nombreuses valeurs conviennent légitimement à être stockées dans l’état.
Par exemple :
const [isOpen, setIsOpen] = useState(false);
Un menu déroulant temporaire ou une fenêtre modale n’a pas besoin d’être reflété du tout dans l’URL.
État interactif
const [activeStep, setActiveStep] = useState(1);
Lorsqu’une valeur déclenche une interaction qui reste entièrement au sein d’un seul composant, la conserver dans l’état local est souvent la bonne solution.
Valeurs qui changent de manière indépendante
Si quelque chose possède réellement son propre cycle de vie, et qu’il n’existe aucun moyen de le calculer à partir des données déjà disponibles, alors l’état est l’endroit approprié pour le stocker.
UI optimiste
Parfois, il est nécessaire d’afficher quelque chose à l’écran avant que le serveur n’ait officiellement confirmé que cela s’est produit.
Ce sont également des utilisations légitimes de l’état.
L’objectif n’est pas de suivre cette règle :
"Utilisez moins de
useState, quoi qu’il arrive."
L’objectif est plutôt celui-ci :
"Assurez-vous que chaque élément d’état ait le bon propriétaire."
Parfois, le bon propriétaire est React.
Parfois, c’est l’URL.
Parfois, c’est le DOM.
Parfois, c’est le serveur.
Parfois, c’est une couche dédiée à la récupération des données ou à la gestion de l’état.
C’est cette décision concernant le propriétaire qui façonne réellement votre architecture.
8. Concentrez-vous sur celui qui possède l’état, et non seulement sur la quantité d’état que vous avez
Ce qui compte vraiment, c’est de donner à chaque élément d’état un propriétaire clair et approprié.
Prenons un tableau de bord qui suit :
Search query
Filters
Pagination
Sort order
Form values
Server data
Loading status
Selected row
Modal visibility
Derived totals
Il est tentant d’insérer chacun de ces éléments dans useState sans y réfléchir.
Mais ces valeurs n’ont pas la même fonction, donc elles ne devraient pas partager le même emplacement.
Un modèle mental plus utile les sépare comme suit :
URL
- Recherche
- Filtres
- Pagination
- Ordre de tri
- Onglets partageables
DOM
- Valeurs de formulaire qui n’ont d’importance qu’une fois le formulaire soumis
Serveur / Couche de données
- Données des clients
- Réponses API
- Données serveur mémorisées
Valeurs dérivées
- Comptages
- Totalités
- Listes filtrées
- Résumés de validation
État React
- Visibilité des modaux
- Sélections temporaires
- État des animations
- Interactions de courte durée
Lorsque vous distribuez l’état de cette manière, le composant a beaucoup moins à synchroniser.
Ce réduction est là que réside le véritable avantage.
9. Les états dupliqués sont à l’origine des bugs de demain
L’état le plus risqué dans une application n’est pas nécessairement le plus complexe.
Souvent, c’est l’état qui existe en même temps en plusieurs endroits.
Imaginez que vous ayez :
const [products, setProducts] = useState([]);
const [filteredProducts, setFilteredProducts] = useState([]);
Vous êtes maintenant responsable de vous assurer que filteredProducts correspond toujours à ce qui se trouve dans products.
Ajoutez un filtre de plus et vous obtiendrez :
const [filteredProducts, setFilteredProducts] = useState([]);
const [searchResults, setSearchResults] = useState([]);
Il existe alors une relation supplémentaire que vous devez maintenir manuellement de manière cohérente.
Tôt ou tard, quelqu’un met à jour les données de base mais oublie d’actualiser l’une des variables dérivées qui en dépendent.
L’interface perd alors silencieusement sa synchronisation avec la réalité.
Finalement, un utilisateur signale quelque chose comme ceci :
"Le compteur indique 42 produits, mais seuls 39 s’affichent à l’écran."
Cette incohérence n’est généralement pas due à une faille dans la logique de filtrage elle-même.
C’est plutôt un symptôme du fait que l’application dispose de plus d’une source de vérité pour les mêmes informations.
Si, au contraire, vous dérivez la valeur :
const filteredProducts = products.filter(...);
Vous éliminez toute une catégorie de bugs avant même qu’ils ne se produisent.
C’est pourquoi réduire l’état ne concerne pas uniquement les performances de rendu.
Il s’agit en réalité de diminuer le nombre d’éléments susceptibles de sortir de synchronisation.
10. Le coût de l’état dépasse les re-rendus
Lorsque les gens discutent de l’état, la conversation porte généralement sur les performances : « Cela provoquera-t-il un autre rendu ? »
C’est une préoccupation légitime, mais ce n’est pas la partie la plus coûteuse de l’équation.
Le véritable coût, c’est la complexité.
Chaque variable d’état supplémentaire représente un élément de plus que votre équipe doit garder en tête.
Puis vous ajoutez inévitablement une appel à un setter.
setSomething(...)
Ensuite, probablement, un useEffect pour y réagir.
useEffect(...)
Puis un tableau de dépendances listant les valeurs qu’il surveille.
[firstValue, secondValue]
Puis une sorte de logique de réinitialisation pour le ramener à sa valeur initiale.
setSomething(initialValue)
Puis un cas limite où cet état doit rester aligné avec un changement de navigation.
Puis un rapport de bug parce que l’état n’a pas été effacé après une certaine mutation.
Petit à petit, la base de code se transforme en un réseau de logiques de synchronisation.
C’est beaucoup plus difficile à comprendre qu’un composant dont les données proviennent de manière claire d’un petit nombre de sources bien définies.
La véritable compétence en React n’est pas de gérer plus d’état
C’est de comprendre où chaque élément d’état doit se trouver.
"Quel état est nécessaire ici ?"
Un meilleur instinct architectural amène à une question différente :
« Quels de ces valeurs ont réellement besoin d’être stockés en état ? »
Et la version la plus précise de cette question est :
« Qui est le propriétaire légitime de chaque élément d’état ? »
Changer votre façon de penser de cette manière peut entièrement modifier l’approche que vous adoptez pour développer des applications React.
L’URL peut gérer l’état de navigation.
Le navigateur peut gérer l’état des formulaires.
Le serveur peut gérer les données qui lui appartiennent.
Les valeurs dérivées peuvent rester telles quelles sans être dupliquées.
Les unions de TypeScript peuvent modéliser des états mutuellement exclusifs.
Et React lui-même peut se concentrer sur l’état interactif à courte durée de vie qui appartient véritablement à la couche UI.
Cette répartition des tâches permet d’obtenir une architecture beaucoup plus claire.
Résumé
Avoir plus d’états n’est pas en soi une réussite.
Un plus grand nombre de variables d’état ne rend pas une application plus performante.
Généralement, cela signifie simplement plus de travail de synchronisation, plus de dépendances à gérer et davantage de risques que les données deviennent incohérentes.
useState, posez-vous les questions suivantes :
- Ce valeur peut-elle être calculée pendant le rendu ? Si c’est le cas, dérivez-la plutôt que de la stocker séparément.
- Faut-il qu’elle survive à un rechargement de page ou puisse être partagée via un lien ? Si oui, placez-la dans les paramètres de recherche de l’URL.
- Ce champ de formulaire doit-il être suivi à chaque frappe ? Sinon, une entrée non contrôlée associée à
FormDatapeut suffire.
L’objectif n’a jamais été de minimiser le nombre brut d’appels à useState.
Il s’agit plutôt de s’assurer que le moins grand nombre possible de valeurs soient responsables de la détermination du comportement de votre application.
Car chaque état inutile représente une chose de plus que votre application doit synchroniser.
Et chaque étape de synchronisation que vous évitez d’écrire est un bug que vous n’aurez jamais à corriger.