Pour une extension de gestion d’abonnements destinée à une salle d’escalade, l’écran de réglages initial en PHP classique (Settings API, champs générés à la main) commençait à montrer ses limites : validation en temps réel impossible sans rechargement de page, retours visuels peu clairs. Plutôt que d’écrire une interface React entièrement sur mesure avec ses propres styles, j’ai choisi de m’appuyer sur @wordpress/components, la même bibliothèque qui alimente l’éditeur de blocs.
Mettre en place l’outillage avec @wordpress/scripts
Plutôt que de configurer manuellement Webpack et Babel, le paquet @wordpress/scripts fournit une configuration prête à l’emploi, identique à celle utilisée par le cœur de WordPress pour ses propres blocs.
npm install --save-dev @wordpress/scripts
npm install @wordpress/components @wordpress/element @wordpress/api-fetch @wordpress/i18n
{
"scripts": {
"start": "wp-scripts start",
"build": "wp-scripts build"
}
}
Ce choix évite de maintenir soi-même une configuration de build, un gain de temps réel sur la durée du projet : chaque montée de version de WordPress met à jour cette configuration en même temps que le reste de l’écosystème des blocs, sans intervention nécessaire côté extension.
Monter l’application React dans l’admin
// admin.php
function escalade_afficher_page_reglages() {
echo '<div id="escalade-reglages-app"></div>';
}
function escalade_charger_script_admin( $hook ) {
if ( 'toplevel_page_escalade-reglages' !== $hook ) {
return;
}
wp_enqueue_script(
'escalade-admin-app',
plugins_url( 'build/index.js', __FILE__ ),
array( 'wp-element', 'wp-components', 'wp-api-fetch', 'wp-i18n' ),
filemtime( plugin_dir_path( __FILE__ ) . 'build/index.js' ),
true
);
wp_enqueue_style( 'wp-components' );
}
add_action( 'admin_enqueue_scripts', 'escalade_charger_script_admin' );

Enregistrer wp-components comme dépendance de style, plutôt que d’écrire une feuille de styles personnalisée, garantit que chaque bouton, champ et notice affiché reprend exactement l’apparence des écrans natifs de l’admin, y compris en cas de changement futur de thème d’administration.
Construire l’interface avec les composants existants
import { render, useState } from '@wordpress/element';
import { Panel, PanelBody, ToggleControl, TextControl, Button, Notice } from '@wordpress/components';
import apiFetch from '@wordpress/api-fetch';
import { __ } from '@wordpress/i18n';
function ReglagesApp() {
const [ dureeGrace, setDureeGrace ] = useState( 7 );
const [ rappelActif, setRappelActif ] = useState( true );
const [ message, setMessage ] = useState( null );
const enregistrer = () => {
apiFetch( {
path: '/escalade/v1/reglages',
method: 'POST',
data: { duree_grace: dureeGrace, rappel_actif: rappelActif },
} ).then( () => {
setMessage( __( 'Réglages enregistrés.', 'escalade-abonnements' ) );
} );
};
return (
<Panel>
<PanelBody title={ __( 'Abonnements', 'escalade-abonnements' ) }>
{ message && <Notice status="success" isDismissible={ false }>{ message }</Notice> }
<TextControl
label={ __( 'Délai de grâce (jours)', 'escalade-abonnements' ) }
type="number"
value={ dureeGrace }
onChange={ ( valeur ) => setDureeGrace( Number( valeur ) ) }
/>
<ToggleControl
label={ __( 'Envoyer un rappel avant échéance', 'escalade-abonnements' ) }
checked={ rappelActif }
onChange={ setRappelActif }
/>
<Button variant="primary" onClick={ enregistrer }>
{ __( 'Enregistrer', 'escalade-abonnements' ) }
</Button>
</PanelBody>
</Panel>
);
}
render( <ReglagesApp />, document.getElementById( 'escalade-reglages-app' ) );
Aucun de ces composants (Panel, ToggleControl, TextControl, Button, Notice) n’a nécessité une seule ligne de CSS supplémentaire : leur apparence, leurs états de focus et leur comportement accessible sont hérités directement de la bibliothèque, la même qui équipe l’éditeur de blocs natif.
apiFetch plutôt que fetch brut
Utiliser fetch() natif face à un endpoint REST de WordPress impose de gérer soi-même l’en-tête X-WP-Nonce, sous peine d’une erreur 403 dès que la session change. apiFetch, fourni par @wordpress/api-fetch, s’en charge automatiquement lorsqu’il est chargé dans le contexte de l’admin, via une configuration injectée par WordPress lui-même.
- Le nonce est automatiquement récupéré depuis
wp-api-fetchlocalisé côté PHP, sans code additionnel dans l’extension - Les erreurs REST (objets
WP_Errortraduits en JSON) remontent sous forme de rejet de promesse, exploitable avec.catch() - Un middleware personnalisé peut être ajouté avec
apiFetch.use()pour, par exemple, injecter un en-tête additionnel propre à l’extension
En résumé
S’appuyer sur @wordpress/components pour un écran d’administration réduit considérablement le travail de conception visuelle et garantit une cohérence immédiate avec le reste de l’admin WordPress. Ce choix impose en contrepartie de suivre les évolutions de cette bibliothèque au fil des versions de WordPress, un compromis largement acceptable pour ce projet au vu du temps gagné sur le design de l’interface elle-même.