# useSelect et useDispatch : lire et modifier les données de l’éditeur

> Deux hooks suffisent à connecter un bloc aux stores de Gutenberg. Voici comment ils fonctionnent réellement, et où les développeurs se trompent le plus souvent.

- Auteur : Clément Hadrot
- Publié le : 2020-02-12
- Mis à jour le : 2020-02-12
- Catégorie : Blocs Gutenberg
- URL : https://wpmoderne.dev.wordpress-developpement.fr/blocs/useselect-usedispatch-lire-modifier-donnees-editeur/

## L’essentiel

- useSelect relit le store à chaque changement
- useDispatch renvoie des actions stables
- Les deux évitent les props qui traversent trop de niveaux

Un client m'a récemment envoyé un bloc qui recevait ses données via cinq niveaux de props, avec un composant intermédiaire dont le seul rôle était de transmettre une valeur qu'il n'utilisait jamais. Le correctif tenait en une ligne : `useSelect`. C'est souvent le symptôme d'une méconnaissance des stores `@wordpress/data`, alors que Gutenberg en expose plusieurs, prêts à l'emploi, dès qu'un bloc a besoin d'informations qui ne lui appartiennent pas en propre.

Ce module de données n'est pas Redux au sens strict, mais il en reprend l'esprit : un état centralisé, des sélecteurs pour le lire, des actions pour le modifier. Deux hooks React, fournis par `@wordpress/data`, donnent accès à ce mécanisme depuis un composant de bloc : `useSelect` pour lire, `useDispatch` pour écrire. Comprendre leur fonctionnement interne évite bien des rendus inutiles et des bugs difficiles à reproduire.

## Les stores que Gutenberg met à disposition

Trois stores reviennent dans la quasi-totalité des blocs : `core/block-editor` expose l'état de l'éditeur de blocs lui-même (sélection, structure de l'arbre, blocs voisins), `core/editor` gère le contenu de l'article en cours d'édition (statut, métadonnées, verrouillage), et `core` centralise les entités REST (articles, pages, types de contenu personnalisés, taxonomies). Un bloc qui veut connaître le titre de l'article courant interroge `core/editor` ; un bloc qui veut savoir combien de blocs sont sélectionnés interroge `core/block-editor`.

Chaque store expose des sélecteurs, des fonctions pures qui prennent l'état global et renvoient une valeur dérivée. Ils sont documentés au fil des versions de Gutenberg et il vaut mieux vérifier leur signature exacte plutôt que de deviner un nom par analogie.

## useSelect : lire sans provoquer de rendus superflus

> L'essentiel à retenir : useSelect relit le store à chaque changement ; useDispatch renvoie des actions stables ; Les deux évitent les props qui traversent trop de niveaux

`useSelect` prend une fonction de rappel qui reçoit `select`, la porte d'entrée vers n'importe quel store enregistré, et un tableau de dépendances optionnel :

```
import { useSelect } from '@wordpress/data';

function TitreArticle() {
	const title = useSelect( ( select ) => {
		return select( 'core/editor' ).getEditedPostAttribute( 'title' );
	}, [] );

	return <p>{ title }</p>;
}
```

Le hook s'abonne automatiquement aux changements du store et ne redéclenche un rendu que si la valeur retournée diffère de la précédente. C'est là que se cache le piège le plus fréquent : renvoyer un nouvel objet ou un nouveau tableau à chaque appel casse cette comparaison, car une nouvelle référence est toujours considérée comme « différente », même si son contenu est identique. Il faut renvoyer des valeurs primitives ou des références stables, quitte à composer plusieurs appels à `useSelect` plutôt qu'un seul retournant un objet complexe.

## useDispatch : obtenir des actions, pas un état

`useDispatch` ne lit rien : il renvoie les créateurs d'actions d'un store, à appeler dans un gestionnaire d'événement.

```
import { useDispatch } from '@wordpress/data';

function BoutonTitre() {
	const { editPost } = useDispatch( 'core/editor' );

	return (
		<button onClick={ () => editPost( { title: 'Nouveau titre' } ) }>
			Renommer
		</button>
	);
}
```

Contrairement aux sélecteurs, les fonctions renvoyées par `useDispatch` sont stables entre les rendus : elles peuvent sans risque être placées dans un tableau de dépendances d'un `useEffect` ou d'un `useCallback` sans provoquer de boucle.

## Deux erreurs qui reviennent en revue de code

- Appeler `useSelect` à l'intérieur d'une condition ou d'une boucle : comme tout hook React, il doit s'exécuter dans le même ordre à chaque rendu.
- Oublier le tableau de dépendances quand le sélecteur dépend d'une valeur externe (un attribut du bloc, par exemple) : le résultat reste alors figé sur sa première évaluation.
- Multiplier les appels à `select( 'core' )` avec des arguments légèrement différents sans mémoriser ces arguments, ce qui déclenche des requêtes REST en boucle lorsque l'entité n'est pas encore en cache.

## Un cas d'usage concret : compter les blocs enfants

Un bloc de type « accordéon » qui doit afficher un compteur de panneaux ouverts illustre bien la complémentarité des deux hooks : `useSelect` lit la liste des blocs enfants via `getBlockOrder` du store `core/block-editor`, et `useDispatch` permet, en retour, de sélectionner un enfant particulier avec `selectBlock` lorsqu'on clique sur un onglet du panneau.

> Sur nos projets, remplacer des props transmises sur trois ou quatre niveaux de composants par un `useSelect` direct au bon endroit réduit systématiquement la taille du fichier de bloc principal, souvent de moitié.

## En résumé

Ces deux hooks suffisent à connecter n'importe quel bloc à l'état global de l'éditeur sans créer de store personnalisé, ce qui reste l'option la plus simple tant que les données manipulées appartiennent déjà à un store existant. Dès qu'un bloc a besoin d'un état qui n'existe dans aucun store natif, en revanche, il faut passer à la création d'un store dédié — un sujet qui mérite un article à part entière.
