# Un conflit de composant natif @wordpress/components qui casse tout

> Un bouton qui perd son style sur des blocs sans rapport entre eux. La cause ne venait d'aucun de ces blocs, mais d'une extension qui redéfinissait un composant partagé.

- Auteur : Clément Hadrot
- Publié le : 2022-01-05
- Mis à jour le : 2022-01-05
- Catégorie : Blocs Gutenberg
- URL : https://wpmoderne.dev.wordpress-developpement.fr/blocs/conflit-composant-natif-wordpress-components/

## L’essentiel

- Les composants partagés sont mutualisés entre tous les blocs actifs
- Une surcharge globale touche des blocs qui n'ont aucun lien entre eux
- L'inspection React DevTools révèle la source du composant réellement monté

Un site e-commerce vendant du matériel de sonorisation professionnelle a vu, du jour au lendemain, l'apparence de plusieurs boutons dans l'éditeur changer sans qu'aucune mise à jour n'ait été appliquée sur les blocs concernés eux-mêmes. Quatre blocs distincts, fournis par trois extensions différentes et sans aucun lien de dépendance apparent entre eux, affichaient soudainement des boutons avec un espacement et une couleur de focus différents de d'habitude. Le réflexe naturel a été de suspecter chaque extension individuellement, en vain : le code de ces quatre blocs n'avait pas changé d'une ligne.

La cause, une fois isolée, s'est révélée bien plus subtile : une cinquième extension, installée récemment pour un besoin totalement différent, redéfinissait globalement le composant `Button` du package `@wordpress/components` en interceptant son export via un filtre webpack maison, dans le but de personnaliser l'apparence de ses propres boutons. Problème : ce composant n'est pas propre à cette extension, il est partagé par l'ensemble de l'écosystème de blocs actifs sur le site.

## Pourquoi @wordpress/components est un terrain partagé

Le package `@wordpress/components` fournit la bibliothèque de composants d'interface utilisée par l'éditeur natif lui-même et par la quasi-totalité des extensions tierces : boutons, contrôles de formulaire, panneaux, info-bulles. Cette mutualisation est un choix délibéré, qui garantit une cohérence visuelle entre les blocs de différentes origines et évite à chaque extension de réinventer ses propres composants de base. Mais elle implique aussi qu'une modification globale de ce package, même bien intentionnée, se propage instantanément à tout ce qui l'utilise, sans distinction d'origine.

## Comment une extension en arrive à modifier un composant partagé

Dans le cas rencontré, l'extension fautive ne redéfinissait pas directement le fichier source de WordPress, ce qui aurait été impossible sans modifier le cœur. Elle interceptait plutôt le composant via le système de filtres JavaScript de `@wordpress/hooks`, en particulier via un filtre appliqué à l'exécution sur le rendu de tous les boutons de l'éditeur, une pratique techniquement valide mais rarement nécessaire pour un besoin qui aurait pu rester local.

```
addFilter(
    'editor.BlockListBlock',
    'mon-extension/style-global-boutons',
    ( BlockListBlock ) => ( props ) => {
        // Modifie un comportement partagé au lieu de rester localisé
        return <BlockListBlock { ...props } className="boutons-personnalises" />;
    }
);
```

> L'essentiel à retenir : Les composants partagés sont mutualisés entre tous les blocs actifs ; Une surcharge globale touche des blocs qui n'ont aucun lien entre eux ; L'inspection React DevTools révèle la source du composant réellement monté

## Diagnostiquer avec React DevTools

L'extension React Developer Tools, installée dans le navigateur, permet d'inspecter l'arbre de composants réellement monté dans l'éditeur et de remonter jusqu'au fichier source qui a produit un composant donné. En sélectionnant un bouton affecté et en consultant l'onglet des props et de la source du composant, il devient possible d'identifier le fichier JavaScript exact d'où provient la surcharge, sans avoir à lire le code de chaque extension une par une.

- Chercher dans l'arbre un composant dont le nom ne correspond pas à celui attendu pour ce bloc.
- Vérifier l'onglet « rendered by » de React DevTools pour remonter au fichier source responsable.
- Désactiver ce composant précis en isolement, plutôt que l'extension entière, pour confirmer l'hypothèse.

## La bonne pratique pour éviter de reproduire ce piège

Pour une extension qui souhaite personnaliser l'apparence de ses propres composants sans affecter le reste du site, la bonne approche consiste à envelopper localement un composant dans un wrapper dédié plutôt que de filtrer un composant partagé de façon globale, ou à utiliser des classes CSS scoping strictement limitées au bloc concerné plutôt qu'un filtre JavaScript à portée générale.

```
function MonBoutonPersonnalise( props ) {
    return <Button { ...props } className="mon-bloc-bouton-specifique" />;
}
```

> Un filtre JavaScript appliqué à un composant partagé de l'éditeur devrait toujours être le dernier recours, jamais la première option envisagée pour un besoin de personnalisation localisée.

## Ce que révèle ce cas sur les audits de code

Ce type de conflit reste particulièrement difficile à détecter lors d'une revue de code classique, puisque le fichier fautif appartient à une extension qui n'a, en apparence, aucun rapport avec les blocs affectés. Seule une recherche explicite des appels à `addFilter` ciblant des hooks partagés de l'éditeur (comme `editor.BlockListBlock` ou `editor.BlockEdit`) à travers l'ensemble des extensions actives permet de repérer ce genre de surcharge avant qu'elle ne cause un incident en production.

## Bilan

Ce cas rappelle qu'un bloc ne vit jamais totalement isolé des autres : il partage un socle de composants avec l'ensemble de l'écosystème actif sur le même site. Un effet de bord observé sur plusieurs blocs sans lien apparent doit systématiquement faire suspecter une modification globale de ce socle partagé, plutôt qu'une coïncidence entre plusieurs bugs indépendants survenus au même moment.
