Erreurs JSX courantes et comment les éviter
JSX semble trompeusement simple — ce n’est que du HTML dans JavaScript, n’est-ce pas ? Pourtant, même les développeurs expérimentés trébuchent sur ses particularités, surtout à mesure que React évolue. Avec le runtime JSX automatique de React 19, les Server Components et le paysage changeant des frameworks modernes, ces erreurs ont de nouvelles implications. Voici ce qui continue de piéger les développeurs et comment éviter ces écueils.
Points clés à retenir
- Les indices de tableau comme clés causent des problèmes de réconciliation et perturbent les fonctionnalités concurrentes de React
- Les Server Components nécessitent des patterns différents des composants client, notamment concernant les API du navigateur
- Le runtime JSX automatique modifie la transformation de votre code et nécessite une configuration appropriée
- Les fonctions inline et les patterns de rendu conditionnel peuvent dégrader silencieusement les performances
L’évolution de JSX : pourquoi les anciennes habitudes cassent le nouveau code
Le runtime JSX automatique introduit dans React 17 a éliminé le besoin d’importer React dans chaque fichier, mais il a également créé une nouvelle confusion. Votre JSX se transforme maintenant différemment — les fonctions jsx remplacent React.createElement, et des outils de build mal configurés peuvent silencieusement casser votre application.
Dans les Server Components, les enjeux sont plus élevés. Du JSX qui fonctionne parfaitement côté client plante lorsqu’il tente d’accéder à window ou utilise des hooks dans le mauvais contexte. Les règles n’ont pas seulement changé ; elles se sont multipliées.
Pièges JSX critiques dans React moderne
1. Clés instables qui détruisent les performances
// ❌ Index comme clé - cause des problèmes de réconciliation
items.map((item, index) => <Item key={index} {...item} />)
// ✅ Identifiant stable et unique
items.map(item => <Item key={item.id} {...item} />)
L’utilisation d’indices de tableau comme clés reste l’une des erreurs JSX les plus dommageables. Dans les fonctionnalités concurrentes de React, les clés instables ne causent pas seulement du scintillement — elles peuvent casser les limites de Suspense et déclencher des re-rendus inutiles dans tout votre arbre de composants.
2. Rendu direct d’objets
// ❌ Les objets ne sont pas des enfants React valides
const user = { name: 'Alice', age: 30 };
return <div>{user}</div>;
// ✅ Rendre des propriétés spécifiques
return <div>{user.name}</div>;
Ce message d’erreur n’a pas changé depuis React 15, pourtant les développeurs tentent toujours de rendre des objets directement. Avec l’inférence JSX de TypeScript, vous détecterez cela au moment de la compilation — si votre tsconfig.json est correctement configuré.
3. Fonctions inline créant de nouvelles références
// ❌ Nouvelle fonction à chaque rendu
<Button onClick={() => handleClick(id)} />
// ✅ Référence stable avec useCallback
const handleButtonClick = useCallback(() => handleClick(id), [id]);
<Button onClick={handleButtonClick} />
Dans le pipeline de rendu de React, les fonctions inline ne causent pas seulement des problèmes de performance — elles cassent l’optimisation memo et peuvent déclencher des mises à jour en cascade dans tout votre arbre de composants.
Discover how at OpenReplay.com.
Server Components : où les règles JSX changent
4. Code client uniquement dans les Server Components
// ❌ Plante dans les Server Components
export default function ServerComponent() {
const width = window.innerWidth; // ReferenceError
return <div style={{ width }} />;
}
// ✅ Utiliser la directive client ou passer depuis le client
'use client';
import { useState, useEffect } from 'react';
export default function ClientComponent() {
const [width, setWidth] = useState(0);
useEffect(() => {
setWidth(window.innerWidth);
}, []);
return <div style={{ width }} />;
}
Les Server Components s’exécutent en dehors du navigateur où les API DOM n’existent pas. Ce n’est pas un problème de configuration — c’est architectural.
5. Composants asynchrones sans Suspense
// ❌ Promise non gérée dans un Server Component
async function UserProfile({ id }) {
const user = await fetchUser(id);
return <div>{user.name}</div>;
}
// ✅ Envelopper avec une limite Suspense
<Suspense fallback={<Loading />}>
<UserProfile id={userId} />
</Suspense>
Les React Server Components peuvent être asynchrones, mais sans limites Suspense appropriées, ils bloqueront soit le rendu, soit planteront avec des erreurs cryptiques.
Pièges de configuration JSX moderne
6. Configuration du runtime JSX incompatible
// ❌ Ancienne transformation dans tsconfig.json
{
"compilerOptions": {
"jsx": "react" // Nécessite les imports React
}
}
// ✅ Runtime automatique pour React 17+
{
"compilerOptions": {
"jsx": "react-jsx" // Pas besoin d'import React
}
}
Le runtime JSX automatique n’est pas seulement une commodité — il est requis pour une taille de bundle optimale et la compatibilité avec les Server Components. Une mauvaise configuration ici cause des échecs silencieux qui ne se manifestent qu’en production.
7. Anti-patterns de rendu conditionnel
// ❌ Retourne 0 au lieu de rien
{count && <Counter value={count} />}
// ✅ Conversion booléenne explicite
{Boolean(count) && <Counter value={count} />}
Quand count vaut 0, JSX rend le nombre 0, pas rien. Cette erreur est particulièrement visible dans React Native où les nœuds texte nécessitent des conteneurs appropriés.
Stratégies de prévention
Configurez correctement vos outils : Configurez ESLint avec eslint-plugin-react et activez ces règles :
react/jsx-keyreact/jsx-no-bindreact/display-name
Utilisez TypeScript : Avec une configuration JSX appropriée, TypeScript détecte la plupart de ces erreurs au moment de la compilation. Activez le mode strict et configurez correctement jsx dans votre tsconfig.json.
Comprenez votre runtime : Sachez si votre composant s’exécute sur le serveur ou le client. Next.js 14+ rend cela explicite avec la directive 'use client', mais le modèle mental s’applique partout.
Conclusion
Les erreurs JSX en 2024 ne concernent pas seulement la syntaxe — elles concernent la compréhension de où et comment votre code s’exécute. Le runtime JSX automatique a changé le modèle de transformation. Les Server Components ont changé le modèle d’exécution. Les fonctionnalités concurrentes de React ont changé le modèle de performance.
Maîtrisez ces fondamentaux, et vous écrirez du JSX qui n’est pas seulement correct, mais optimisé pour les capacités de React moderne. Le meilleur JSX est invisible — il s’efface et laisse vos composants briller.
FAQ
Lorsque vous utilisez des indices de tableau comme clés, React ne peut pas suivre correctement quels éléments ont changé, bougé ou été supprimés. Cela force React à re-rendre plus de composants que nécessaire et peut causer l'association de l'état au mauvais composant après réorganisation.
Bien que les fonctions inline fonctionnent d'un point de vue fonctionnel, elles créent de nouvelles références à chaque rendu, cassant les optimisations React.memo et causant potentiellement le re-rendu inutile des composants enfants. Pour une meilleure maintenabilité, utilisez useCallback pour les gestionnaires d'événements qui dépendent des props ou de l'état.
Le paramètre react utilise la transformation classique React.createElement nécessitant des imports React dans chaque fichier. Le paramètre react-jsx utilise le runtime automatique introduit dans React 17, qui gère la transformation sans imports React explicites et produit des bundles plus petits.
Gain Debugging Superpowers
Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers. Check our GitHub repo and join the thousands of developers in our community.