Un développeur maintenant un bloc « Accordéon » depuis plusieurs années se heurtait à une limitation persistante : le composant InnerBlocks, tel qu’il l’utilisait depuis ses débuts avec Gutenberg, imposait systématiquement son propre élément div englobant les blocs enfants, un wrapper supplémentaire qui venait s’intercaler entre le conteneur du bloc et son contenu réel. Pour un composant d’accordéon dont chaque ligne devait respecter une structure CSS précise (flexbox avec un ordre d’éléments spécifique), ce wrapper superflu cassait systématiquement la mise en page, obligeant à des contournements CSS peu satisfaisants.
Le hook useInnerBlocksProps, apparu avec l’apiVersion 2 de l’éditeur de blocs, répond exactement à ce problème en permettant de fusionner les props du conteneur de blocs enfants directement sur l’élément DOM de son choix, sans imposer de wrapper intermédiaire.
Le problème du composant InnerBlocks historique
Avec l’ancienne approche, le composant InnerBlocks se plaçait comme un enfant du conteneur du bloc, générant automatiquement son propre élément DOM :
// Ancienne approche : un wrapper supplémentaire est généré
export default function Edit() {
const blockProps = useBlockProps();
return (
<div { ...blockProps }>
<InnerBlocks />
</div>
);
}
Le HTML final comportait alors deux niveaux de div imbriqués, l’un pour le bloc lui-même, l’autre généré par InnerBlocks, une structure rarement souhaitée quand le CSS attendait un contact direct entre le conteneur et ses enfants.
La fusion de props avec useInnerBlocksProps
import { useBlockProps, useInnerBlocksProps } from '@wordpress/block-editor';
export default function Edit() {
const blockProps = useBlockProps();
const innerBlocksProps = useInnerBlocksProps( blockProps, {
template: [ [ 'mon-agence/ligne-accordeon' ] ],
templateLock: false,
} );
return <div { ...innerBlocksProps } />;
}
Ici, un seul élément div porte à la fois les props du bloc lui-même et celles nécessaires à l’affichage des blocs enfants : plus aucun wrapper intermédiaire ne s’intercale, le CSS flexbox de l’accordéon s’applique enfin exactement comme prévu.

Le même hook côté save()
La fonction save() suit exactement le même principe, avec l’appel équivalent useInnerBlocksProps.save(), qui reçoit les props statiques du conteneur plutôt que celles générées par useBlockProps côté édition.
import { useBlockProps, useInnerBlocksProps } from '@wordpress/block-editor';
export default function save() {
const blockProps = useBlockProps.save();
const innerBlocksProps = useInnerBlocksProps.save( blockProps );
return <div { ...innerBlocksProps } />;
}
Migrer un bloc existant sans tout réécrire
La migration depuis l’ancien composant InnerBlocks ne nécessite pas de réécriture complète du bloc : l’essentiel du changement se limite au remplacement du composant JSX par l’appel au hook, en conservant les mêmes options de template et de verrouillage déjà en place. Le passage à apiVersion: 3 dans block.json, généralement effectué en parallèle, active par ailleurs l’éditeur en mode iframe, ce qui impose de vérifier que les styles CSS chargés côté éditeur restent bien disponibles dans ce nouveau contexte.
- Le hook accepte les mêmes options que l’ancien composant : template, templateLock, allowedBlocks.
- Un seul élément DOM porte désormais toutes les props nécessaires, plus besoin d’imbrication artificielle.
- La rétrocompatibilité avec le contenu déjà publié reste assurée tant que le balisage final produit par save() reste identique.
Un point de vigilance : la validation de contenu
Un changement de structure DOM entre l’ancienne et la nouvelle version de save() déclenche une invalidation de tout le contenu déjà publié avec ce bloc, l’éditeur détectant une différence entre le HTML stocké et celui que produirait la nouvelle fonction. Une déprecation correctement déclarée via la propriété deprecated du bloc reste indispensable pour migrer en douceur sans casser le contenu existant.
Ne migrez jamais un save() en production sans vérifier, sur un échantillon réel de contenu publié, que l’éditeur ne signale aucun bloc invalide après le déploiement.
Pour aller plus loin
useInnerBlocksProps a largement remplacé l’ancien composant dans la documentation officielle et dans les blocs natifs de WordPress eux-mêmes, à commencer par le bloc Groupe et le bloc Colonnes. Pour tout nouveau bloc composé, il n’y a aujourd’hui plus aucune raison de repartir sur l’ancienne approche, sinon la simple habitude d’un code existant qui fonctionne encore, en attendant sa prochaine occasion de refonte.