Como añadir un metabox en React a Gutenberg
Recientemente me vi en la necesidad de agregar controles al editor de bloques de WordPress, o Gutenberg como también se le llama al proyecto, esto normalmente es muy sencillo pero tenía un par de complejidades que no había visto antes:
- Debía tener controles en React y
- Debía posicionarse en la parte inferior del editor
Estos requisitos por si mismos no son mayor problema, pero juntos era algo que no se acostumbra a hacer.
El problema
El asunto aquí es que es sencillo hacer ambas cosas por separado, podemos agregar un nuevo plugin al editor y mostrarlo en la parte lateral (el sidebar), ó, podemos agregar un metabox con PHP y se mostrará automáticamente en la parte inferior del editor.
¿Ven el problema? No hay forma de agregar un plugin de Gutenberg en la parte inferior, y no podemos agregar controles React en PHP.
…¿O si?
La solución
Resulta que la solución es mucho más simple de lo que pensaba, lo que necesitamos es una combinación de ambas para que esto funcione, básicamente, podemos hacer lo siguiente.
- Crear un metabox que aparezca en la parte inferior de la página, este únicamente mostrará un contenedor
- Creamos un plugin de Gutenberg con la funcionalidad react que necesitamos, este se mostrará en el sidebar por defecto
- Creamos un portal que mueva nuestro componente en React a nuestro contenedor dentro del metabox
¡Esa es la magia! Ahora veamos como podemos hacerlo con código.
¿Portal?
Esto merece su propio post, pero a grandes rasgos los portales nos permiten mover partes de nuestros componentes a cualquier sitio dentro del DOM, pero mantienen su estructura dentro de nuestra aplicación en React.
Registrar un Metabox en WordPress
Ahora, si queremos hacerlo con código, lo primero que debemos hacer es crear un Plugin que agregue nuestro metabox:
1<?php23/**4 * Plugin Name: Mah React metabox5 * Author: Mario Aguiar6 * Author URI: https://www.marioaguiar.net7 * Plugin URI: https://www.marioaguiar.net8 * Version: 1.09 */1011namespace Mah;1213/**14 * Maneja las funcionalidades de metabox15 */16class Metabox17{18 /**19 * Agrega los hooks necesarios20 *21 * @return void22 */23 public function init(): void24 {25 add_action('add_meta_boxes', [$this, 'register_metabox']);26 }2728 /**29 * Agrega un metabox30 *31 * @return void32 */33 public function register_metabox(): void34 {35 add_meta_box(36 'mah-metabox',37 __('Mah metabox'),38 function () {39 echo "<div id='mah-metabox-content'></div>";40 },41 null,42 'normal',43 'high'44 );45 }46}4748(new Metabox())->init();49
Esto lo que hará será agregar un nuevo metabox al editor de blocks, si no fijamos bien, podemos adivinar que está vacío (aunque más bien simplemente no tiene texto), algo así:

Registrar un Plugin en Gutenberg
Esto nos servirá como el contenedor de nuestro componente en React, ahora, para nuestro componente podemos agregar un nuevo archivo, simplemente creamos un plugin de Gutenberg utilizando registerPlugin:
1/**2 * WordPress dependencies3 */4import { registerPlugin } from '@wordpress/plugins';5import { PluginDocumentSettingPanel } from '@wordpress/editor';67registerPlugin('mah-metabox', {8 render: () => {9 return (10 <PluginDocumentSettingPanel name='mah-metabox' title='Mah Metabox'>11 <h2>Mah Metabox</h2>12 </PluginDocumentSettingPanel>13 );14 },15});16
No olvidemos agregar nuestro archivo al editor:
1/**2 * Agrega los hooks necesarios3 *4 * @return void5 */6public function init(): void7{8 // …9 add_action('enqueue_block_editor_assets', [$this, 'enqueue_assets']);10}11
1/**2 * Agrega los scripts y dependencias en nuestro plugin3 *4 * @return void5 */6public function enqueue_assets(): void7{8 $asset_file = include plugin_dir_path(__FILE__) . 'build/index.asset.php';910 wp_enqueue_script(11 'mah-metabox',12 plugin_dir_url(__FILE__) . 'build/index.js',13 $asset_file['dependencies'],14 $asset_file['version'],15 true16 );17}18
Y el resultado sería algo así:

Ahora tenemos los dos componentes que necesitamos, y estamos preparados para juntarlos.
¿Qué es PluginDocumentSettingPanel
?
Este es un componente de Gutenberg que nos permite agregar controles al editor de bloques, en este caso lo estamos utilizando para mostrar nuestro componente en el sidebar.
A pesar de lo que esto podría hacernos pensar (y lo sencillo que sería hacer todo esto), no existe una alternativa que nos permita mostrar nuestro componente en la parte inferior del editor.
Juntando el plugin de Gutenberg con nuestro Metabox
Por fortuna, esto es increiblemente sencillo gracias al anteriormente mencionado createPortal
,
simplemente necesitamos modificar nuestro plugin para crear un portal y enviar nuestro componente
a través de ese portal:
1/**2 * WordPress dependencies3 */4import { createPortal } from '@wordpress/element';5import { registerPlugin } from '@wordpress/plugins';67const Metabox = () => <h2>Mah Metabox</h2>;89const MetaboxPortal = () =>10 createPortal(<Metabox />, document.querySelector('#mah-metabox-content'));1112registerPlugin('mah-metabox', {13 render: MetaboxPortal,14});15
¡Listo! Eso es todo lo que necesitamos, lo que estamos haciendo es crear un portal hacia nuestro
elemento con id mah-metabox
, así, cuando React ejecute MetaboxPortal
sabrá que tiene que enviar
su contenido a través del portal, y terminará mostrando nuestro componente justo en el lugar que
necesitamos, que es nuestro metabox:

Conclusión
Esto resulta bastante útil cuando necesitamos más espacio del que nuestra sidebar puede darnos, un buen ejemplo es el plugin Yoast SEO que muestra la información del post debajo del editor, lo cual hace que editarlo sea mucho más sencillo.
Una vez seguidos todos estos pasos, sólo necesitamos agregar nuestros controles como si estuvieramos
trabajando en cualquier otro proyecto de React, y listo, ya tenemos un metabox en React en Gutenberg.
Con la ventaja de poder acceder a los datos del post y modificarlos directamente desde nuestro componente
a travez de los componentes en @wordpress/data
.
