« Too many re-renders. React limits the number of renders to prevent an infinite loop. » Ce message, affiché dans la console du navigateur, accompagné d’un éditeur totalement figé ou d’un onglet qui consomme le processeur à pleine charge, signale presque toujours la même cause : un appel à setAttributes déclenché sans condition suffisante à l’intérieur d’un useEffect, lui-même redéclenché par le changement qu’il vient de provoquer.
Symptôme
Le bloc concerné, une fois inséré dans l’éditeur, provoque un blocage quasi immédiat de l’interface. Le message d’erreur mentionné apparaît dans la console, parfois précédé de plusieurs centaines de lignes de rendu successives visibles dans les outils de développement React si l’extension est installée. Dans les cas moins francs, aucun message n’apparaît, mais l’éditeur devient perceptiblement plus lent à chaque insertion du bloc, signe d’une boucle qui se stabilise sans dépasser la limite stricte de React mais consomme malgré tout des cycles de rendu inutiles.
Diagnostic
Le code fautif ressemble presque toujours à ceci :
useEffect( () => {
setAttributes( { largeurCalculee: largeurConteneur * ratio } );
} ); // pas de tableau de dépendances : exécuté à chaque rendu
Sans tableau de dépendances, l’effet s’exécute après chaque rendu du composant. Comme il appelle setAttributes, qui déclenche lui-même un nouveau rendu, la boucle se referme immédiatement : rendu, effet, mise à jour d’attribut, nouveau rendu, et ainsi de suite sans jamais s’arrêter. Même avec un tableau de dépendances présent, le problème persiste si la valeur recalculée à l’intérieur de l’effet est elle-même l’une de ses propres dépendances, ou si un objet ou tableau recréé à chaque rendu (donc jamais strictement égal au précédent) figure dans ce tableau.
Vérifier la vraie source de la boucle
Pour confirmer le diagnostic sans deviner, un simple console.log placé au tout début du composant Edit, affichant un compteur incrémenté à chaque montage, permet de mesurer objectivement la fréquence des rendus avant de conclure. Une boucle réelle produit des dizaines, voire des centaines d’appels en quelques secondes, alors qu’un rendu normal, même redondant, reste limité à quelques occurrences.

Correctif
La correction la plus directe consiste à déclarer un tableau de dépendances précis, limité aux valeurs qui doivent réellement déclencher le recalcul, et à comparer la nouvelle valeur à l’ancienne avant d’appeler setAttributes :
useEffect( () => {
const largeurRecalculee = largeurConteneur * ratio;
if ( largeurRecalculee !== attributes.largeurCalculee ) {
setAttributes( { largeurCalculee: largeurRecalculee } );
}
}, [ largeurConteneur, ratio ] );
Le tableau de dépendances limite les déclenchements aux seuls changements pertinents (largeurConteneur et ratio), et la comparaison explicite empêche setAttributes d’être appelé lorsque la valeur calculée est identique à celle déjà stockée, ce qui coupe définitivement la boucle même si l’effet venait à se redéclencher pour une autre raison.
Prévention
- Ne jamais écrire un
useEffectqui appellesetAttributessans avoir explicitement réfléchi à son tableau de dépendances. - Comparer systématiquement l’ancienne et la nouvelle valeur avant d’écrire, dès qu’un effet peut potentiellement se redéclencher lui-même.
- Préférer, quand c’est possible, un calcul dérivé directement dans le rendu (sans
useEffectnisetAttributes) plutôt que de stocker une valeur qui peut être recalculée à la volée.
La question à se poser avant d’écrire un
useEffectdans un bloc : cette valeur a-t-elle vraiment besoin d’être stockée en attribut, ou peut-elle simplement être calculée à chaque rendu sans passer par un effet ? La seconde option supprime le risque de boucle par construction.
Le cas particulier de la synchronisation avec une donnée externe
Ce type de boucle apparaît fréquemment lorsqu’un bloc synchronise un attribut avec une donnée qui change de source (une réponse d’API, une mesure du DOM via une référence). Dans ce cas, le tableau de dépendances doit inclure la source réelle du changement (la référence, la donnée d’API), jamais l’attribut lui-même dérivé de cette source, sous peine de recréer exactement la même boucle sous une forme légèrement différente.
En résumé
« Too many re-renders » désigne presque toujours un setAttributes déclenché sans condition suffisante à l’intérieur d’un effet qui se redéclenche lui-même. Un tableau de dépendances précis et une comparaison explicite de la valeur avant écriture suffisent, dans l’immense majorité des cas, à retrouver un bloc stable et un éditeur réactif.