Un champ « durée de lecture estimée » qu’un client voulait pouvoir corriger manuellement, affiché dans un bloc en haut d’article : la mauvaise solution consiste à stocker cette valeur comme un attribut du bloc. La bonne solution consiste à en faire une métadonnée d’article, lue et modifiée depuis le bloc via useEntityProp, sans qu’elle ne transite jamais par le contenu HTML sauvegardé.
Pourquoi un meta plutôt qu’un attribut de bloc
Un attribut de bloc vit dans le contenu de l’article, sérialisé sous forme de commentaire HTML au moment de la sauvegarde. Une métadonnée (post meta) vit dans une table séparée de la base de données, indépendante du contenu. Cette distinction compte dès qu’une donnée doit rester accessible même si le bloc qui l’affiche est supprimé de l’article, ou doit être interrogeable directement en base ou via une requête WP_Query avec meta_query — ce qu’un attribut de bloc ne permet pas.
Étape 1 : enregistrer le meta côté PHP
<?php
add_action( 'init', function () {
register_post_meta( 'post', 'duree_lecture', [
'type' => 'integer',
'single' => true,
'show_in_rest' => true,
'default' => 0,
] );
} );
show_in_rest à true est la condition indispensable : sans cette clé, le meta reste invisible depuis l’API REST, donc invisible depuis l’éditeur de blocs, qui s’appuie entièrement sur cette API pour lire et écrire les données de l’article.
Étape 2 : déclarer que le bloc utilise les métadonnées
{
"usesContext": [ "postId", "postType" ]
}
Cette déclaration dans block.json donne accès à l’identifiant et au type de l’article courant, nécessaires pour que useEntityProp sache sur quelle entité lire et écrire.
Étape 3 : lire et écrire avec useEntityProp

import { useEntityProp } from '@wordpress/core-data';
import { TextControl } from '@wordpress/components';
export default function Edit( { context } ) {
const [ meta, setMeta ] = useEntityProp(
'postType',
context.postType,
'meta'
);
return (
<TextControl
label="Durée de lecture (minutes)"
type="number"
value={ meta.duree_lecture }
onChange={ ( valeur ) =>
setMeta( { ...meta, duree_lecture: Number( valeur ) } )
}
/>
);
}
useEntityProp renvoie un couple valeur/setter, sur le modèle de useState, mais branché directement sur l’entité REST de l’article. Toute modification via setMeta marque automatiquement l’article comme modifié, ce qui active le bouton « Mettre à jour » sans code supplémentaire — c’est ce comportement qui distingue ce hook d’un simple appel à apiFetch manuel.
Un piège fréquent : écraser les autres clés du meta
La ligne { ...meta, duree_lecture: Number( valeur ) } n’est pas cosmétique : meta regroupe toutes les métadonnées exposées en REST pour l’article, pas seulement celle manipulée par ce bloc. Écrire directement setMeta( { duree_lecture: valeur } ) écraserait silencieusement toutes les autres métadonnées déjà enregistrées par d’autres blocs ou extensions.
Où s’arrête ce hook
- Il ne fonctionne que sur des entités exposées en REST (articles, pages, types personnalisés avec
show_in_rest), pas sur des options globales du site. - Il ne remplace pas un champ ACF ou un champ personnalisé complexe avec une logique de validation métier poussée, qui reste plus à l’aise côté PHP.
- Il ne gère pas la révision ni l’historique du meta : contrairement au contenu de l’article, les métadonnées ne sont pas versionnées par le système de révisions natif.
Un champ qui doit rester interrogeable indépendamment du contenu de l’article — une note interne, une date d’expiration, un identifiant externe — appartient presque toujours à un meta, jamais à un attribut de bloc.
En résumé
useEntityProp offre une synchronisation propre entre un champ affiché dans un bloc et une métadonnée réelle de l’article, à condition d’avoir correctement exposé cette métadonnée en REST côté PHP.