Crear una página de opciones en WordPress con React – Parte 2
En la primera parte de este tutorial, mostré los principios básicos para crear una página de opciones en WordPress, en esta segunda parte, mostraré como utilizar los componentes incluidos en WordPress para agregar campos de texto, y guardar las opciones.
Tabla de Contenido
- Paso 1: Creando nuestra aplicación
- Paso 2: Agrega algunas opciones
- Paso 3: Crear opciones en el backend
- Paso 4: Agregar botón de guardado con React
Es posible que necesites instalar algunos paquetes para este tutorial. Aunque gracias a nuestro compilador en @wordpress/scripts que automáticamente los agrega a las dependencias del script podría no ser necesario, yo prefiero instalarlos simplemente para tener un registro de ellos.
Si llegas a tener algún error simplemente ejecuta npm install --save-dev {paquete}
con los siguientes paquetes:
– @wordpress/components
– @wordpress/element
– @wordpress/i18n
Paso 1: Creando nuestra aplicación
Para crear una página de opciones, necesitamos agregar algunos campos.
Para comenzar, debemos abrir el archivo settings.js
que es donde iniciaremos
nuestra aplicación, y creamos una sencilla:
settings.js
1/**2 * WordPress dependencies3 */4import { createRoot } from '@wordpress/element';5/**6 * Internal dependencies7 */8import Settings from './components/settings';9const rootElement = document.querySelector('#mah-settings');10if (rootElement) {11 createRoot(rootElement).render(<Settings />);12}13
components/settings.js
1/**2 * WordPress dependencies3 */4import { __ } from '@wordpress/i18n';5const Settings = () => {6 return <h1>{__('Selecciona las opciones deseadas', 'mah-settings')}</h1>;7};8export default Settings;9
Entre las cosas que ponemos observar en este pedazo de código están:
- El uso de createRoot con el que iniciamos nuestras aplicaciones en React, pero
a diferencia de como normalmente se usa, ésta vez lo tomamos de
@wordpress/element
. Esto es porque WordPress ya viene con su propia copia de React que nos asegura que sus componentes funcionarán. - Así mismo, viene con una versión en javascript de la función
__
para traducciones, a diferencia de PHP no hay versión deesc_html__
así que utilizamos la versión normal.
Uso de React
Como te puedes dar cuenta por este pequeño código (y el título del post…). Éste tutorial asume que tienes al menos un conocimiento básico de ReactJS, si no es así; te invito a estudiarlo un poco para que no pierdas el hilo de este tema.
Paso 2: Agrega algunas opciones
Ahora que tenemos nuestra aplicación corriendo podemos comenzar a agregar opciones a nuestra página, una de las más comunes que me encuentro es la de campos de texto, tal vez para algún API, por ejemplo:
1/**2 * WordPress dependencies3 */4import { Card, CardBody, TextControl } from '@wordpress/components';5import { useState } from '@wordpress/element';6import { __ } from '@wordpress/i18n';7const Settings = () => {8 const [apiKey, setApiKey] = useState('');9 return (10 <>11 <h1>{__('Selecciona las opciones deseadas', 'mah-settings')}</h1>12 <Card>13 <CardBody>14 <TextControl15 help={__('Ingresa tu API key', 'mah-settings')}16 label={__('API Key', 'mah-settings')}17 onChange={setApiKey}18 value={apiKey}19 />20 </CardBody>21 </Card>22 </>23 );24};25export default Settings;26
Al volver a recargar la página, podremos ver que ¡nuestra página de opciones toma forma! aunque podemos agregar algo de sabor, pero eso lo haremos más adelante, ahora que tenemos nuestro campo, expliquemos que pasa aquí:
- Se agregan algunos componentes más de WordPress, esta vez son
Card
,CardBody
, yTextControl
. En realidad el importante es TextControl ya que es el que utilizaremos para ingresar nuestras opciones - Importamos
useState
de@wordpress/element
(una vez más, React viene incluido) - Agregamos un estado vacío que se actualizará cuando cambiemos algo en
TextControl
- El uso de fragmentos de React, solo que utilizamos su versión recortada, en lugar
de
import { Fragment } from '@wordpress/element'
simplemente utilizamos<></>

@wordpress/components
viene con muchos componentes disponibles, sugiero
revisar el Storybook
para ver una demostración que los que tenemos a nuestra disposición
Como bonus, agreguemos un toggle
simplemente porque me gusta como funcionan:
1/**2 * WordPress dependencies3 */4import {5 Card,6 CardBody,7 CardDivider,8 TextControl,9 ToggleControl,10} from '@wordpress/components';11import { useState } from '@wordpress/element';12import { __ } from '@wordpress/i18n';13const Settings = () => {14 const [apiKey, setApiKey] = useState('');15 const [toggled, setToggled] = useState(false);16 return (17 <>18 <h1>{__('Selecciona las opciones deseadas', 'mah-settings')}</h1>19 <Card>20 <CardBody>21 <TextControl22 help={__('Ingresa tu API key', 'mah-settings')}23 label={__('API Key', 'mah-settings')}24 onChange={setApiKey}25 value={apiKey}26 />27 </CardBody>2829 <CardDivider />3031 <CardBody>32 <ToggleControl33 label={__('Activar funcionalidad', 'mah-settings')}34 onChange={setToggled}35 checked={toggled}36 />37 </CardBody>38 </Card>39 </>40 );41};42export default Settings;43
¿Qué pasó?
Si recargamos la página, nos damos cuenta de que nuestro toggle
se ve más bien como un checkbox, ¿qué pasó?

Lo que sucede es que a pesar de que nuestras dependencias de javascript se agregan
automáticamente a nuestro script, no sucede lo mismo con nuestras dependencias de estilos.
Por lo que puede ser necesario que las agreguemos nosotros mismos al archivo
class-mah-settings.php
de una forma similar a lo que hicimos con el script de javascript:
class-mah-settings.php
1/**2 * Registra los scripts y estilos.3 *4 * @return void5 */6public function enqueue_scripts(): void {7 $screen = get_current_screen();8 if ( $screen->id !== $this->menu_slug ) {9 return;10 }11 $asset = include $this->plugin_path . '/build/settings.asset.php';12 wp_enqueue_script(13 'mah-settings',14 plugins_url() . '/mah-settings-react/build/settings.js',15 $asset['dependencies'],16 $asset['version'],17 true18 );19 wp_enqueue_style( 'wp-components' );20}21
Al volver a recargar la página veremos el resultado deseado, y si nos fijamos bien, también nuestro campo de texto mejoró en apariencia:

Paso 3: Registrar las opciones en el backend
Para poder guardar nuestras opciones, necesitamos tener valores en la base de datos a donde guardarlos, WordPress se maneja básicamente con los siguientes tipos:
En nuestro caso utilizaremos las opciones globales, debido a la naturaleza de nuestra página de opciones.
En php, podemos registrarlas de esta forma:
php/class-mah-settings.php
1/**2 * Registra los hooks.3 *4 * @return void5 */6public function init(): void {7 add_action( 'admin_menu', [ $this, 'add_menu_page' ] );8 add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_scripts' ] );9 add_action( 'admin_init', [ $this, 'register_settings' ] );10 add_action( 'rest_api_init', [ $this, 'register_settings' ] );11}12
php/class-mah-settings.php
1/**2 * Registra las opciones.3 *4 * @return void5 */6public function register_settings(): void {7 register_setting(8 'mah_settings',9 'mah_api_key',10 [11 'description' => __( 'API Key', 'mah-settings' ),12 'sanitize_callback' => 'sanitize_text_field',13 'show_in_rest' => true,14 'type' => 'string',15 ]16 );17 register_setting(18 'mah_settings',19 'mah_function',20 [21 'description' => __( 'Funcion X', 'mah-settings' ),22 'show_in_rest' => true,23 'type' => 'boolean',24 ]25 );26}27
El segundo hook rest_api_init es necesario para poder utilizar nuestras
opciones en React, de lo contrario show_in_rest
no tendría ningún efecto
Paso 4: Agregar botón de guardado con React
Ahora sólo necesitamos guardar nuestras opciones desde el lado de React, para lo cual necesitamos agregar un botón de guardado a nuestra aplicación, y agregar un evento cuando éste sea presionado:
1/**2 * WordPress dependencies3 */4import {5 Button,6 Card,7 CardBody,8 CardDivider,9 CardFooter,10 TextControl,11 ToggleControl,12} from '@wordpress/components';13import { useState } from '@wordpress/element';14import { __ } from '@wordpress/i18n';15const Settings = () => {16 const [apiKey, setApiKey] = useState('');17 const [toggled, setToggled] = useState(false);18 const saveSettings = () => {19 console.log('Guardar');20 };21 return (22 <>23 <h1>{__('Selecciona las opciones deseadas', 'mah-settings')}</h1>24 <Card>25 <CardBody>26 <TextControl27 help={__('Ingresa tu API key', 'mah-settings')}28 label={__('API Key', 'mah-settings')}29 onChange={setApiKey}30 value={apiKey}31 />32 </CardBody>3334 <CardDivider />3536 <CardBody>37 <ToggleControl38 label={__('Activar funcionalidad', 'mah-settings')}39 onChange={setToggled}40 checked={toggled}41 />42 </CardBody>4344 <CardFooter>45 <Button disabled={!apiKey} onClick={saveSettings} variant='primary'>46 {__('Guardar', 'mah-settings')}47 </Button>48 </CardFooter>49 </Card>50 </>51 );52};53export default Settings;54
Una breve explicación de lo que acabamos de agregar:
- Traemos un nuevo componente
CardFooter
, que nos ayudará a mantener el estilo de nuestra tarjeta - Traemos el componente
Button
que viene con WordPress, esto nos brinda unas ventajas más sobre utilizar botones regulares, como el que ya viene con estilos por ejemplo, en esta ocasión utilizamos la varianteprimary
. Y nos aseguramos de que se mantenga deshabilitado si el campo de API key no ha sido llenado - Agregamos la función saveSettings que se encargará de guardar nuestras opciones
Así al dar click al botón veremos como en la consola se registra nuestra acción, ahora sólo debemos reemplazarla por la verdadera función de guardado.

Próximamente…
Mi idea original era terminar el tutorial en esta parte, pero me di cuenta de lo largo que se está volviendo el post y aún quedan bastantes conceptos que quiero tocar, así que he decidido que éste es un buen momento para terminar este post y regresar la próxima semana con una tercera parte en donde guardaremos nuestras opciones, terminaremos de crear una página de opciones; y veremos conceptos como:
- El uso de
useDispatch
,useEntityProp
, ysaveEditedEntityRecord
- Mejoras de UX para nuestra página
- Introducción general al paquete
@wordpress/data
y el uso de stores.
Mientras tanto puedes revisar el código de ésta segunda parte en mi repositorio.
Como siempre son bienvenidos tus comentarios y sugerencias sobre que cosas te gustaría ver explicadas en este humilde blog. ¡Hasta la próxima!
Leer más
Notas al pie
-
Muy populares en los días de auje de customizer, los theme mods están ligados al tema que se usa en nuestro sitio, en caso de que el tema cambie, los mods también desaparecen, pero regresan cuando el tema al que están ligados vuelva a seleccionarse. Pero con la llegada de FSE, estos comienzan a ser irrelevantes en mi opinión ↩︎ ↩
-
Los post meta, son básicamente los attributos que están ligados a un post en específico, estos pueden cambiar de post a post ↩︎ ↩
-
Utilizados para opciones globales que pueden ser utilizadas ya sea por un tema o por un plugin, sin importar que post o tema esté seleccionado en el sitio ↩︎ ↩