Chapitre 8.7 — Les data stores (@wordpress/data)
⏱️ TL;DR —
@wordpress/dataest un store global façon Redux qui expose toutes les données de WordPress à vos composants : les entités (posts, meta, users, taxonomies) via le storecore, l’état de l’éditeur viacore/editor, etc. On lit avecuseSelectet on agit avecuseDispatch— deux hooks qui vous seront immédiatement familiers. Pour lire/écrire une meta du post courant, le hookuseEntityPropest le raccourci idéal. C’est ce qui relie vos blocs React aux données du CMS, sans écrire d’appels REST à la main.
🎯 Objectifs
- Comprendre le modèle store/select/dispatch.
- Lire des données avec
useSelect(entités, requêtes). - Modifier des données avec
useDispatch/useEntityProp. - Gérer le chargement (
isResolving) et éviter les pièges.
1. Le modèle : stores, sélecteurs, actions
@wordpress/data organise l’état en stores nommés, chacun avec des sélecteurs (lecture) et des actions (écriture) :
| Store | Contient |
|---|---|
core | Les entités : posts/CPT, meta, users, taxonomies, médias, réglages du site. |
core/editor | L’état de l’éditeur de post (post courant, statut, sauvegarde). |
core/block-editor | L’état des blocs (sélection, blocs, insertion). |
core/notices | Les notifications (afficher un message). |
💡 Pour un dev React — C’est Redux (le vrai :
@wordpress/datas’en inspire directement).useSelect=useSelector,useDispatch=useDispatch. La grande différence : les données WordPress (posts, meta, users) sont déjà dans le storecore, avec résolution automatique — vous demandezgetEntityRecords('postType','livre'), le store fait le fetch REST pour vous et met en cache. Vous ne câblez pas d’appels API : vous sélectionnez de la donnée qui se charge toute seule.
2. Lire avec useSelect
import { useSelect } from '@wordpress/data';
import { store as coreStore } from '@wordpress/core-data';
function useLivres() {
return useSelect( ( select ) => {
const query = { per_page: 20, _fields: 'id,title' };
const livres = select( coreStore ).getEntityRecords( 'postType', 'livre', query );
const isResolving = select( coreStore ).isResolving( 'getEntityRecords', [ 'postType', 'livre', query ] );
return { livres, isResolving };
}, [] );
}getEntityRecords('postType', 'livre', query): récupère une liste de livres (le store appelle/wp/v2/livreen coulisses).isResolving(...): indique si la donnée est en cours de chargement (pour afficher unSpinner).- Le second argument
[](dépendances) fonctionne comme pouruseMemo/useEffect.
⚠️ Piège n°1 —
nullpendant le chargement. Un sélecteur d’entité renvoieundefined/nulltant que la donnée n’est pas chargée (puis se met à jour et re-render). Gérez ce cas (if ( ! livres ) return <Spinner/>;), sinonlivres.map(...)plante. C’est le pendant du « data peut être undefined » de vos hooks de fetch.
3. Lire/écrire une meta du post courant : useEntityProp
Pour les blocs qui éditent une métadonnée du post en cours d’édition (ex. le prix d’un livre depuis un bloc dans l’éditeur du livre), useEntityProp est le raccourci :
import { useEntityProp } from '@wordpress/core-data';
function ChampPrix() {
const [ meta, setMeta ] = useEntityProp( 'postType', 'livre', 'meta' );
const prix = meta?.wpr_prix ?? '';
return (
<input
type="number"
value={ prix }
onChange={ ( e ) => setMeta( { ...meta, wpr_prix: e.target.value } ) }
/>
);
}useEntityPropretourne un couple[valeur, setter](commeuseState) relié à l’entité courante.- La sauvegarde se fait quand l’utilisateur enregistre le post (l’éditeur gère la persistance via la REST API).
- Prérequis : la meta doit être enregistrée avec
show_in_rest(ch. 7.4) — sinon elle n’est pas exposée au store.
⚠️ Piège n°2 — meta non exposée. Si
useEntityProp('meta')ne « voit » pas votre champ, c’est que la meta n’a pas été enregistrée avecregister_post_meta(..., show_in_rest => true)(ch. 7.4). Le storecorene connaît que ce que la REST API expose.
4. Agir avec useDispatch
Pour déclencher des actions (créer une notice, sauvegarder, insérer un bloc) :
import { useDispatch } from '@wordpress/data';
import { store as noticesStore } from '@wordpress/notices';
function Bouton() {
const { createSuccessNotice } = useDispatch( noticesStore );
return (
<button onClick={ () => createSuccessNotice( 'Enregistré !' ) }>
Enregistrer
</button>
);
}useDispatch(store) renvoie les actions du store (comme dispatch lié à un slice). On l’utilise pour interagir avec l’éditeur, les notices, ou des stores custom.
5. Appels directs : @wordpress/api-fetch
Quand vous voulez appeler un endpoint custom (Partie 9) sans passer par le store d’entités :
import apiFetch from '@wordpress/api-fetch';
const data = await apiFetch( { path: '/wpr-books/v1/stats' } );apiFetch est pré-configuré : base REST, nonce d’authentification, gestion des erreurs. C’est votre client HTTP pour les routes maison (ch. 9). Pour les entités standard, préférez le store core (cache, réactivité) ; pour de la logique custom, apiFetch.
✏️ Exercices
- Reliez :
useSelect,useDispatch, storecore— à leurs équivalents Redux. - Vous voulez une liste déroulante des livres du catalogue dans votre bloc. Quel sélecteur, et comment gérer le chargement ?
- Pour éditer le prix d’un livre depuis un bloc placé dans l’éditeur du livre, quel hook, et quel prérequis côté PHP ?
✅ Solution
useSelect≈useSelector(lecture) ;useDispatch≈useDispatch(actions) ; le storecore≈ un slice contenant déjà les entités WordPress (avec résolution/fetch automatique).select(coreStore).getEntityRecords('postType','livre', query); gérer le chargement avecisResolving(...)(afficher unSpinner) et le casundefined/nullavant que les données n’arrivent (puis re-render).useEntityProp('postType','livre','meta')(couple[meta, setMeta]) ; prérequis : la meta doit être enregistrée avecregister_post_meta(..., 'show_in_rest' => true)pour être exposée au store.
🧠 Quiz de révision
1. Qu’est-ce que @wordpress/data ?
Un store global (façon Redux) exposant les données de WordPress via des sélecteurs et actions.
2. Quel hook pour lire des données ? Pour agir ?
useSelect (lecture) et useDispatch (actions).
3. Quel store contient les entités (posts, meta, users) ?
Le store core (@wordpress/core-data), avec résolution/fetch automatique.
4. Quel hook pour lire/écrire une meta du post courant ?
useEntityProp( 'postType', type, 'meta' ) (nécessite la meta exposée en REST).
5. Comment appeler un endpoint REST custom depuis un bloc ?
Avec apiFetch({ path: '/mon-plugin/v1/…' }) (nonce et base gérés automatiquement).
Chapitre suivant : Variations, transforms & styles.