Dix pièges cachés des composants React qui ralentissent les applications à l’ère React 19
Dix erreurs courantes des composants React, allant du manque d’HTML sémantique à l’omission de la mémorisation, pourquoi React 19 et le React Compiler ne les cachent pas, avec des solutions.
Sources: 10 React Component Mistakes That Are Secretly Breaking Your App in 2026
Les composants React semblent simples tant que de petits erreurs ne s’accumulent pas pour créer des problèmes d’accessibilité, ralentir le rendu et générer des bugs difficiles à détecter. React 19, le React Compiler et les Server Components ont changé la manière dont les applications sont construites, ce qui rend ces erreurs encore plus coûteuses, et non moins. Voici dix erreurs au niveau des composants qui nuisent discrètement à une application, accompagnées de la solution pour chacune d’elles.
1. Utiliser <div> partout au lieu d’HTML sémantique
L’erreur : Recourir à un <div> générique pour chaque élément UI. La navigation devient un <div>. Un bouton se transforme en <div onClick={...}>. Un article est entouré d’un <div>. Même une étiquette de formulaire reçoit le même traitement.
// ❌ Bad: Div soup
function Navbar() {
return (
<div className="navbar">
<div className="logo" onClick={() => router.push('/')}>Logo</div>
<div className="nav-links">
<div className="nav-item" onClick={() => setPage('home')}>Home</div>
<div className="nav-item" onClick={() => setPage('about')}>About</div>
</div>
</div>
);
}
Pourquoi cela endommage votre application :
- Problèmes d’accessibilité : les technologies d’assistance ne parviennent pas à reconnaître les points de navigation, les contrôles interactifs ou les titres. Une personne utilisant un lecteur d’écran entend quelque chose comme « cliquable, texte : Accueil » au lieu de « navigation, lien, Accueil ».
- Accès au clavier défaillant : les balises
<div>ne sont pas par défaut ciblables, ce qui empêche quiconque se déplace avec un clavier d’accéder à votre menu de navigation via la touche Tab. - SEO affaibli : les moteurs de recherche s’appuient sur des balises sémantiques telles que
<nav>,<main>et<article>pour analyser la structure d’une page. Une page entièrement constituée de<div>est perçue comme du contenu de faible qualité par les robots de recherche. - Les composants serveur dans React 19 : étant donné que le SSR et le streaming font que le chargement initial d’HTML est ce que voient à la fois les utilisateurs et les bots avant que l’hydratation ne commence, la structure sémantique devient encore plus importante.
La solution :
// ✅ Good: Semantic HTML
function Navbar() {
return (
<nav className="navbar" aria-label="Main navigation">
<a href="/" className="logo">Logo</a>
<ul className="nav-links">
<li><a href="/">Home</a></li>
<li><a href="/about">About</a></li>
</ul>
</nav>
);
}
Meilleure pratique en 2026 : profitez de la nouvelle API use dans React 19 ainsi que des métadonnées d’accessibilité, et faites passer vos composants par des outils d’audit tels que axe-core ou l’extension de navigateur WAVE. Utilisez <button> pour tout élément cliquable, <nav> pour les blocs de navigation, et <section> associé à aria-labelledby pour délimiter une région d’une page.
2. Styles en ligne dans JSX (impact négatif sur les performances)
L’erreur : définir des objets de style en ligne à l’intérieur de JSX, ce qui génère une nouvelle référence d’objet à chaque rendu.
// ❌ Bad: New object every render
function Badge({ color, children }) {
return (
<span style={{ backgroundColor: color, padding: '4px 8px', borderRadius: '4px' }}>
{children}
</span>
);
}
Pourquoi cela endommage votre application :
- Travail supplémentaire de réconciliation : comme un nouvel objet de style est créé à chaque rendu, la logique de comparaison de React détecte une propriété « modifiée » et affecte le nœud DOM même si rien n’a réellement changé.
- Performance ralentie avec CSS-in-JS : les bibliothèques qui analysent les déclarations de style en ligne paient ce prix à plusieurs reprises, aggravant ainsi le problème.
- Points aveugles du compilateur : le compilateur de React 19 est capable de mémoriser les composants, mais il ne peut pas stabiliser par lui-même les références à des objets en ligne. Dès qu’il détecte un objet nouvellement créé, il omet d’optimiser cette partie.
- Opportunités de mise en cache manquées : les navigateurs ne peuvent pas mettre en cache les déclarations de style en ligne de la même manière qu’ils le font pour les feuilles de style. Une classe CSS est analysée une seule fois, tandis que les styles en ligne sont réanalysés à chaque chargement du composant.
La solution :
// ✅ Good: CSS classes with dynamic data attributes
function Badge({ color, children }) {
return (
<span
className="badge"
data-color={color}
style={{ '--badge-color': color }}
>
{children}
</span>
);
}
// CSS
// .badge { background-color: var(--badge-color); padding: 4px 8px; border-radius: 4px; }
Par ailleurs, les outils de Tailwind CSS fonctionnent bien lorsqu’ils sont utilisés avec prudence et des valeurs arbitraires :
// Acceptable: Tailwind utility classes
function Badge({ color, children }) {
return (
<span className="px-2 py-1 rounded" style={{ backgroundColor: color }}>
{children}
</span>
);
}
Meilleure pratique en 2026 : intégrer les styles statiques dans des modules CSS, des classes Tailwind ou une approche CSS-in-JS sans exécution à temps de charge. Réserver les styles en ligne aux valeurs véritablement dynamiques, comme la largeur d’une barre de progression, et même dans ce cas, privilégier les propriétés personnalisées CSS lorsque c’est possible.
3. Ne pas utiliser correctement la propriété key dans les listes
L’erreur : se fier à l’index de l’array comme clé, omettre complètement la propriété key, ou générer une clé aléatoire à chaque rendu.
// ❌ Bad: Index as key
function TodoList({ todos }) {
return (
<ul>
{todos.map((todo, index) => (
<li key={index}>{todo.text}</li>
))}
</ul>
);
}
// ❌ Worse: Random key
function TodoList({ todos }) {
return (
<ul>
{todos.map((todo) => (
<li key={Math.random()}>{todo.text}</li>
))}
</ul>
);
}
Pourquoi cela endommage votre application :
- Clés basées sur un index : lorsque les éléments de la liste sont réordonnés, React associe la même clé à la même position, ce qui entraîne une réutilisation du mauvais nœud DOM pour l’élément incorrect. Cela mélange l’état des entrées, le focus et l’état interne des composants entre les éléments.
- Clés générées aléatoirement : comme une nouvelle clé est créée à chaque rendu, React détruit et reconstruit chaque nœud DOM à chaque mise à jour. Cela détériore les performances et efface tout état de formulaire dans la liste.
- Transitions de React 19 : avec le rendu concurrent et les transitions activées, des clés défectueuses peuvent provoquer des distorsions visibles dans l’interface utilisateur ainsi que des états corrompus lorsque une mise à jour est interrompue.
La solution :
// ✅ Good: Stable, unique identifier
function TodoList({ todos }) {
return (
<ul>
{todos.map((todo) => (
<li key={todo.id}>{todo.text}</li>
))}
</ul>
);
}
Si aucun identifiant unique naturel n’est disponible, créez-en un dès la production des données et non au moment de l’affichage :
// At data creation, not in the component
const todos = items.map(item => ({
...item,
id: crypto.randomUUID(), // or your backend's ID
}));
Meilleure pratique en 2026 : Lorsqu’une liste provient d’un composant serveur, assurez-vous que le serveur lui-même fournit des identifiants stables. Évitez de dériver des clés à partir de la position dans un tableau, sauf si la liste est véritablement statique et ne croît que par l’ajout de nouveaux éléments.
4. Modifier directement les props
L’erreur : Traiter les props comme s’il s’agissait de variables locales modifiables et les modifier à l’intérieur d’un composant enfant.
// ❌ Bad: Mutating props directly
function SortButton({ items }) {
const handleSort = () => {
items.sort((a, b) => a.price - b.price); // MUTATES the prop!
onSort(items);
};
return <button onClick={handleSort}>Sort by Price</button>;
}
Pourquoi cela endommage votre application :
- Corruption silencieuse du composant parent : L’état du parent est modifié sans que l’on sache jamais que cela s’est produit. La détection des changements de React repose sur la comparaison des références, ce qui fait que la mutation reste complètement inaperçue.
- Bug de réaffichage obsolète : Comme
itemsfait toujours référence au même tableau en mémoire, le composant parent ne se réaffiche jamais, ce qui fait que l’interface affiche des données dépassées. - Confusion du compilateur React : Le compilateur suppose que les props circulent de manière immuable à travers votre arborescence. Les modifier directement invalide sa logique de mémorisation automatique.
- Perte de prévisibilité : Tout autre composant qui fait référence au même tableau verra soudainement la version modifiée et triée sans avertissement.
La solution :
// ✅ Good: Immutable update
function SortButton({ items, onSort }) {
const handleSort = () => {
const sorted = [...items].sort((a, b) => a.price - b.price);
onSort(sorted);
};
return <button onClick={handleSort}>Sort by Price</button>;
}
Meilleure pratique en 2026 : optez pour Immer lorsque les mutations imbriquées semblent inévitables, et installez une règle ESLint telle que prefer-readonly-props si vous utilisez TypeScript. Partez du principe que chaque propriété est readonly tant que cela n’a pas été prouvé autrement.
5. Trop de propriétés (au lieu de composition)
L’erreur : créer des « composants dieu » complexes qui acceptent une douzaine ou plus de propriétés uniquement pour gérer toutes les variations internes possibles.
// ❌ Bad: Prop explosion
function Card({
title,
subtitle,
imageUrl,
imageAlt,
showImage,
imagePosition,
actions,
showActions,
actionAlignment,
badge,
badgeColor,
onBadgeClick,
footer,
showFooter,
footerContent,
borderRadius,
shadow,
padding,
variant,
}) {
return (
<div className={`card card--${variant}`} style={{ borderRadius, padding, boxShadow: shadow }}>
{showImage && (
<div className={`card__image card__image--${imagePosition}`}>
<img src={imageUrl} alt={imageAlt} />
</div>
)}
<div className="card__content">
<h2>{title}</h2>
{subtitle && <p>{subtitle}</p>}
</div>
{/* ... more conditional rendering ... */}
</div>
);
}
Pourquoi cela endommage votre application :
- Une interface API fragile : Chaque nouvelle exigence signifie l’ajout d’une autre propriété, une modification des parties internes du composant, et un risque que d’autres éléments soient endommagés.
- Des bundles encombrés : Le composant finit par importer et exécuter des chemins de code pour des fonctionnalités dont l’utilisation réelle n’a jamais besoin.
- Une couverture de tests difficile : Vous êtes contraint de valider une matrice de combinaisons de propriétés en constante augmentation.
- Des problèmes avec React Server Components : Des listes de propriétés surchargées ont tendance à transférer plus de logique au client que ce qui est vraiment nécessaire.
La solution :
// ✅ Good: Composition
function Card({ children, className }) {
return (
<div className={clsx('card', className)}>
{children}
</div>
);
}
function CardImage({ src, alt, position = 'top' }) {
return (
<div className={`card__image card__image--${position}`}>
<img src={src} alt={alt} loading="lazy" />
</div>
);
}
function CardContent({ title, subtitle }) {
return (
<div className="card__content">
<h2>{title}</h2>
{subtitle && <p>{subtitle}</p>}
</div>
);
}
function CardActions({ children, align = 'end' }) {
return (
<div className={`card__actions card__actions--${align}`}>
{children}
</div>
);
}
// Usage
<Card>
<CardImage src="/photo.jpg" alt="Product" />
<CardContent title="Headphones" subtitle="Noise cancelling" />
<CardActions>
<button>Add to Cart</button>
</CardActions>
</Card>
Meilleure pratique en 2026 : privilégiez plutôt le modèle de composant composé ou la composition basée sur des slots. Laissez l’utilisateur du composant décider de la structure et du contenu ; le composant lui-même ne doit fournir que le conteneur.
6. Ne pas utiliser React.Fragment (Divs inutiles)
L’erreur : envelopper des éléments frères dans un simple <div> uniquement pour respecter la règle de JSX selon laquelle un composant doit retourner un seul nœud racine.
// ❌ Bad: Wrapper div for layout that breaks semantics
function TableCell({ label, value }) {
return (
<div> {/* This div breaks the <table> structure! */}
<td>{label}</td>
<td>{value}</td>
</div>
);
}// ❌ Bad: Extra div in a list
function ListItems({ items }) {
return (
<ul>
{items.map(item => (
<div key={item.id}> {/* Invalid HTML: div inside ul */}
<li>{item.name}</li>
<li>{item.description}</li>
</div>
))}
</ul>
);
}
Pourquoi cela endommage votre application :
- Marquage invalide : un
<div>n’est pas un enfant valide pour des éléments tels que<table>,<ul>,<select>ou<dl>. Les navigateurs réécriront silencieusement le DOM pour corriger cela, ce qui provoque des incohérences lors de l’hydratation pendant le rendu côté serveur. - Interférence avec le layout : des éléments d’encapsulation supplémentaires perturbent le fonctionnement de CSS Grid, Flexbox ainsi que la propriété
gap. - Échecs d’hydratation dans React : étant donné la popularité actuelle du SSR en flux et des composants serveur, ce type de nesting invalide peut provoquer des incohérences fatales lors de l’hydratation, entraînant la panne de l’application côté client.
La solution :
// ✅ Good: React.Fragment
function TableCell({ label, value }) {
return (
<>
<td>{label}</td>
<td>{value}</td>
</>
);
}
// ✅ Good: Fragment with key (required in lists)
function ListItems({ items }) {
return (
<ul>
{items.map(item => (
<React.Fragment key={item.id}>
<li>{item.name}</li>
<li>{item.description}</li>
</React.Fragment>
))}
</ul>
);
}
Meilleure pratique en 2026 : utilisez l’abréviation <> </> lorsque vous n’avez pas besoin de clé, et recourez à <React.Fragment key={...}> pour afficher des tableaux de fragments qui en nécessitent une. Vérifiez périodiquement l’arbre des composants dans React DevTools afin de détecter et de supprimer les divs d’encapsulation inutiles.
7. Affichage de nombres faux avec && (bugs cachés)
L’erreur : compter sur && pour afficher conditionnellement quelque chose, sans tenir compte des cas où l’opérande de gauche évalue à 0, NaN ou une chaîne vide.
// ❌ Bad: Shows "0" on screen when items.length is 0
function Cart({ items }) {
return (
<div>
<h1>Shopping Cart</h1>
{items.length && (
<ul>
{items.map(item => <li key={item.id}>{item.name}</li>)}
</ul>
)}
</div>
);
}
// ❌ Bad: accountBalance could be 0
function AccountSummary({ account }) {
return (
<div>
{account.balance && <p>Balance: ${account.balance}</p>}
</div>
);
}
Pourquoi cela endommage votre application :
- React affiche réellement
0: écrire{0 && <Component />}ne produit rien, il affiche plutôt le nombre littéral0en tant que texte. - Défauts visuels invisibles : les utilisateurs se retrouvent à fixer un « 0 » étranger quelque part sur la page, ce qui donne l’impression que quelque chose ne fonctionne pas et peut perturber le layout.
- Valeurs zéro dans la réalité : des éléments tels que les soldes de compte, le nombre d’articles ou les scores sont fréquemment égaux à zéro de manière valide et attendue. Considérer
0comme faux avec&&signifie que vous affichez soit rien lorsque vous ne le devriez pas, soit le chiffre lui-même lorsque vous ne le souhaitez pas.
La solution :
// ✅ Good: Explicit boolean check
function Cart({ items }) {
return (
<div>
<h1>Shopping Cart</h1>
{items.length > 0 && (
<ul>
{items.map(item => <li key={item.id}>{item.name}</li>)}
</ul>
)}
</div>
);
}
// ✅ Good: Nullish coalescing for defaults, ternary for conditionals
function AccountSummary({ account }) {
return (
<div>
{account.balance != null ? (
<p>Balance: ${account.balance}</p>
) : (
<p>Loading balance...</p>
)}
</div>
);
}
Meilleure pratique en 2026 : éviter complètement l’utilisation de && pour le rendu conditionnel. Préférez une expression ternaire (condition ? : null) ou utilisez explicitement une valeur booléenne avec quelque chose comme Boolean(count) && .... Ajoutez une règle ESLint à votre projet pour signaler les patterns à risque impliquant && dans le JSX.
8. Omettre la mémorisation pour du JSX coûteux
L’erreur : permettre à un sous-arbre coûteux de se rérender à chaque mise à jour de son parent, même lorsque les props concernés n’ont pas réellement changé.
// ❌ Bad: HeavyChart re-renders every time Parent re-renders
function Dashboard({ data, filter }) {
const [hoveredItem, setHoveredItem] = useState(null);
return (
<div>
<Sidebar onHover={setHoveredItem} />
<HeavyChart data={data} filter={filter} /> {/* Re-renders on every hover! */}
<Tooltip item={hoveredItem} />
</div>
);
}
function HeavyChart({ data, filter }) {
// Expensive SVG rendering, D3 calculations, etc.
return <svg>{/* thousands of nodes */}</svg>;
}
Pourquoi cela endommage votre application :
- Calculs inutiles :
HeavyChartréexécute sa logique de rendu même lorsquedataetfilterrestent inchangés. - Perte de frames : si le rendu de
HeavyChartprend environ 50 ms, un simple événement de survol sur une barre latérale peut réduire le taux de rafraîchissement à environ 20 fps. - Limites du compilateur React : la mémorisation automatique assurée par le compilateur fonctionne au sein d’un composant, mais elle ne peut pas optimiser entre composants si le parent continue à transmettre des références de fonctions de rappel nouvellement créées.
La solution :
// ✅ Good: Memoize the expensive component
const HeavyChart = memo(function HeavyChart({ data, filter }) {
// Expensive rendering
return <svg>{/* thousands of nodes */}</svg>;
});
function Dashboard({ data, filter }) {
const [hoveredItem, setHoveredItem] = useState(null);
// Stabilize the callback if passed to children
const handleHover = useCallback((item) => setHoveredItem(item), []);
return (
<div>
<Sidebar onHover={handleHover} />
<HeavyChart data={data} filter={filter} />
<Tooltip item={hoveredItem} />
</div>
);
}
Meilleure pratique en 2026 : le compilateur de React 19 réduit le besoin de mémorisation manuelle dans les cas simples, mais pour des sous-arborescences véritablement lourdes, il reste utile d’envelopper le code avec memo. Utilisez le Profilleur des outils de développement de React pour identifier les véritables goulots d’étranglement avant de recourir à la mémorisation.
9. Fusion de la présentation et de la logique métier
L’erreur : créer un seul composant qui récupère simultanément des données, les transforme, suit l’état du formulaire, exécute des effets secondaires et rend le markup.
// ❌ Bad: God component
function UserProfile({ userId }) {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
const [isEditing, setIsEditing] = useState(false);
const [formData, setFormData] = useState({});
useEffect(() => {
fetchUser(userId).then(data => {
setUser(data);
setFormData(data);
setLoading(false);
});
}, [userId]);
const handleSubmit = async () => {
await updateUser(userId, formData);
setIsEditing(false);
};
if (loading) return <Spinner />;
return (
<div>
<h1>{user.name}</h1>
{isEditing ? (
<form onSubmit={handleSubmit}>
<input
value={formData.name}
onChange={e => setFormData({...formData, name: e.target.value})}
/>
</form>
) : (
<button onClick={() => setIsEditing(true)}>Edit</button>
)}
</div>
);
}
Pourquoi cela endommage votre application :
- Difficile à tester : vous ne pouvez pas vérifier la logique de récupération des données sans charger l’ensemble du composant, et vous ne pouvez pas tester l’interface affichée sans simuler la couche réseau.
- Non réutilisable : le comportement du formulaire est enfermé dans ce seul composant et ne peut pas être partagé ailleurs.
- Difficile à comprendre : l’état, les effets secondaires et le markup sont entremêlés, de sorte qu’un petit ajustement de l’interface peut accidentellement perturber la logique de traitement des données.
- Compatibilité médiocre avec les composants serveur : selon les conventions de 2026, la récupération des données doit se faire dans les composants serveur, tandis que les composants client devraient être réservés à l’interactivité.
La solution :
// ✅ Good: Separated concerns
// Container / Logic Hook
function useUserProfile(userId) {
const { data: user, isLoading } = useQuery({
queryKey: ['user', userId],
queryFn: () => fetchUser(userId),
});
const updateMutation = useMutation({
mutationFn: updateUser,
onSuccess: () => queryClient.invalidateQueries({ queryKey: ['user', userId] }),
});
return { user, isLoading, updateUser: updateMutation.mutate };
}
// UI Component
function UserProfile({ userId }) {
const { user, isLoading, updateUser } = useUserProfile(userId);
const [isEditing, setIsEditing] = useState(false);
if (isLoading) return <Spinner />;
return (
<div>
<h1>{user.name}</h1>
{isEditing ? (
<UserProfileForm
initialData={user}
onSubmit={(data) => {
updateUser({ userId, ...data });
setIsEditing(false);
}}
onCancel={() => setIsEditing(false)}
/>
) : (
<button onClick={() => setIsEditing(true)}>Edit</button>
)}
</div>
);
}
// Reusable Form Component
function UserProfileForm({ initialData, onSubmit, onCancel }) {
const [formData, setFormData] = useState(initialData);
return (
<form onSubmit={(e) => { e.preventDefault(); onSubmit(formData); }}>
<input
value={formData.name}
onChange={e => setFormData(prev => ({...prev, name: e.target.value}))}
/>
<button type="submit">Save</button>
<button type="button" onClick={onCancel}>Cancel</button>
</form>
);
}
Approche recommandée pour 2026 : diviser les responsabilités en hooks personnalisés pour la logique, en composants purement présentationnels pour le markup, et en composants serveur pour le chargement des données. Un composant doit soit effectuer une action, soit afficher quelque chose ; il est rare qu’un même composant parvienne à bien assumer les deux fonctions.
10. Ne pas utiliser les interfaces TypeScript pour les props
L’erreur : s’appuyer sur prop-types, des commentaires JSDoc dispersés, ou, dans le pire des cas, ignorer complètement la vérification des types des props.
// ❌ Bad: No types
function Button(props) {
return <button className={props.variant}>{props.children}</button>;
}
// ❌ Bad: PropTypes at runtime only
import PropTypes from 'prop-types';
function Button(props) {
return <button className={props.variant}>{props.children}</button>;
}
Button.propTypes = {
variant: PropTypes.string,
children: PropTypes.node,
};
Pourquoi cela endommage votre application :
- Échecs silencieux : les fautes d’orthographe dans les noms de propriétés, l’absence de valeurs requises et les types incompatibles se manifestent par des plantages en temps de exécution au lieu d’être détectés avant le déploiement.
- Le refactoring devient difficile : renommer une seule propriété vous oblige à rechercher manuellement dans l’ensemble du codebase, tandis qu’un système de types indique immédiatement tous les endroits où des mises à jour sont nécessaires.
- Expérience utilisateur moins bonne : sans types, vous perdez l’autocomplétion, les suggestions de documentation en ligne ainsi que la protection offerte par les renommages automatiques.
- Alignement insuffisant avec React 19 : les nouvelles fonctionnalités de React telles que les composants serveur, l’utilisation de
useavec des Promises et le redirigeant de références sont conçues en tenant compte du modèle de types de TypeScript ; donc, omettre les types signifie perdre les garanties en temps de compilation sur lesquelles ces fonctionnalités reposent.
La solution :
// ✅ Good: Explicit TypeScript interface
interface ButtonProps {
variant?: 'primary' | 'secondary' | 'danger';
size?: 'sm' | 'md' | 'lg';
disabled?: boolean;
onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void;
children: React.ReactNode;
type?: 'button' | 'submit' | 'reset';
}
function Button({
variant = 'primary',
size = 'md',
disabled = false,
onClick,
children,
type = 'button'
}: ButtonProps) {
return (
<button
type={type}
className={`btn btn--${variant} btn--${size}`}
disabled={disabled}
onClick={onClick}
>
{children}
</button>
);
}
Méthode recommandée pour 2026 : activez le mode strict (strict: true dans tsconfig.json). Définissez les propriétés des modèles à l’aide de déclarations interface plutôt que d’alias type, car les interfaces génèrent généralement des messages d’erreur plus clairs et sont plus faciles à étendre. Utilisez React.ComponentProps lorsque vous devez dériver des types à partir d’éléments HTML natifs lors de la création de composants d’enveloppe. Évitez absolument d’utiliser any pour les types de propriétés en toutes circonstances.
Résumé : La liste de contrôle des composants pour 2026
Avant de fusionner un composant, passez en revue cette liste de contrôle :
- [ ] Avez-vous choisi du HTML sémantique plutôt que d’empiler des éléments
<div>génériques ? - [ ] Les styles sont-ils définis en CSS plutôt que via des objets de style en ligne ?
- [ ] Les éléments de liste reposent-ils sur des valeurs
keystables et uniques ? - [ ] Les props sont-ils toujours traités comme lus uniquement ?
- [ ] Le composant peut-il être composé, plutôt que de nécessiter une douzaine de props de configuration ?
- [ ] Avez-vous remplacé les divs d’encapsulation inutiles par
Fragment? - [ ] Les rendus conditionnels sont-ils écrits sous forme de ternaires ou de vérifications booléennes explicites à la place de
&&? - [ ] Le JSX coûteux est-il mémorisé là où c’est important ?
- [ ] La logique métier est-elle séparée du markup, stockée dans des hooks ou des fonctions utilitaires ?
- [ ] Tous les props sont-ils pleinement décrits à l’aide d’interfaces TypeScript ?
Aucune de ces erreurs ne fera planter votre application dès le premier jour. Au contraire, elles la détériorent progressivement, en accumulant des défauts en matière d’accessibilité, en entraînant une perte de performance insidieuse et en provoquant des corruptions subtiles de l’état. Les corriger dès maintenant signifie que votre codebase React résistera à la prochaine mise à jour du framework, à la prochaine grande refonte, ainsi qu’à toute équipe qui prendra ultérieurement en charge la maintenance de ce que vous avez construit.