Cómo consultar usuarios en Gutenberg
Hace algunos meses me vi en la necesidad de crear un pequeño bloque en Gutenberg que hiciera una consulta para conseguir datos de usuarios en WordPress. Me sorprendí un poco de lo poco documentada que está esta sección así que he decidio escribir un pequeño tutorial mostrando cómo es que logré consultar usuarios en Gutenberg.
Para que las cosas sean más sencillas de digerir, escribiré un pequeño bloque que simplemente dejará seleccionar a un autor en el sitio y mostrará su información. Comencemos:
TABLA DE CONTENIDO
- PASO 1: LA BASE DE EL BLOQUE
- PASO 2: LA ESTRUCTURA
- PASO 3: GUARDANDO LA SELECCIÓN
- PASO 4: MOSTRAR LA INFORMACIÓN DEL USUARIO
- PASO 4.1: MOSTRAR EL DROPDOWN SI NINGÚN USUARIO HA SIDO SELECCIONADO
- PASO 4.2: MOSTRAR UNA VISTA PREVIA DE LOS DATOS DEL USUARIO QUE SE SELECCIONA
- PASO 4.3: OFRECER CONTROLES PARA CAMBIAR DE USUARIO DESDE LA VISTA PREVIA
- PASO 4.4: OFRECER UNA FORMA DE ELIMINAR LA SELECCIÓN Y VOLVER AL DROPDOWN (OPCIONAL)
PASO 1: LA BASE DE EL BLOQUE
Comenzaremos con la creación básica del bloque, no voy a profundizar mucho en este tema porque realmente no es el punto de este tutorial, pero para hacer las cosas más sencillas utilizaré la herramienta oficial de WordPress @wordpress/create-block
:
Simplemente necesitamos ejecutar estos comandos (slug
es el nombre del directorio donde se creará el plugin).
1npx @wordpress/create-block@latest mah-users --wp-env2cd mah-users3npx wp-env start4npm start5
Utilizando wp-env
La bandera wp-env
nos permite crear un ambiente local en el que funcionará nuestro plugin, si ya tienes un ambiente que usas para pruebas esto no es necesario.
Si no eres muy familiar con ambientes locales te invito a ver mi video Creando un ambiente local para WordPress con WP-ENV en youtube donde explico una manera fácil de lograrlo con las herramientas que ofrece WordPress.
Una vez que tenemos nuestro plugin funcionando, podemos comenzar a crear el bloque.
PASO 2: LA ESTRUCTURA
Como mencioné anteriormente, lo que queremos es crear una selección de usuarios, y que al seleccionarlos se muestren los datos del usuario seleccionado, así que para ello necesitaremos sólo un atributo, que será el ID del usuario que queremos mostrar:
Entonces en nuestro block.json
agregamos el atributo:
1"attributes": {2 "userId": {3 "type": "number"4 }5}6
Este tutorial esta pensado para ser un bloque dinámico (dynamic block), por lo que sólo mostraremos el funcionamiento del editor de bloque. No entraré a fondo sobre cómo se muestra un bloque dinámico en el frontend, pero si quieres que lo haga déjame un comentario y lo veremos en un futuro.
PASO 2.1: LA SELECCIÓN
Como necesitamos seleccionar usuarios, podemos utilizar uno de los componentes que ya existen en WordPress para ello, así que en el archivo edit.js
podemos importar el componente llamado SelectControl
y mostrarlo en el editor:
Para importamos el componente al principio del archivo:
1import { SelectControl } from '@wordpress/components';2
Y dentro de la función Edit
lo regresamos:
1export default function Edit() {2 return (3 <div { ...useBlockProps() }>4 <SelectControl5 label={ __( 'Selecciona un usuario', 'mah-users' ) }6 value={ 'user1' }7 options={ [8 { label: 'Usuario 1', value: 'user1' },9 { label: 'Usuario 2', value: 'user2' },10 { label: 'Usuario 3', value: 'user3' },11 ] }12 />13 </div>14 );15}16
Si estás siguiendo este tutorial y te preguntas por qué el select
se ve azul… Es porque create-block
agrega algunos estilos por defecto a los archivos, para eliminarlos simplemente elimina el contenido de los archivos style.scss
y editor.scss
.
Una vez hecho esto, tendremos algo similar a esta imagen:

PASO 2.2: LOS DATOS REALES
Nuestro select box está funcionando, pero es claro que no como queremos, para empezar, los datos no nos dicen nada, lo primero que debemos hacer, es hacer una consulta a la base de datos para que muestre las opciones con base en los datos que existen en nuestro sitio.
Entonces, podemos hacer uso del método getUsers
que está disponible en el paquete @wordpress/core-data
.
Para empezar, debemos importar nuestros componentes, regresamos al principio del archivo y agregamos lo siguiente:
1import { store as coreStore } from '@wordpress/core-data';2import { useSelect } from '@wordpress/data';3
Y hacemos una llamada select
para tener nuestra consulta, esto es dentro de la función Edit
:
1const records = useSelect( ( select ) => {2 const { getUsers } = select( coreStore );34 return getUsers( {5 per_page: -1, // Seleccionar a todos los usuarios.6 _fields: 'id,name', // Solo regresa el ID, y el Nombre.7 context: 'view', // Indica que solo queremos ver los datos, no editarlos. Esto reduce los campos a sólo lo que necesitemos.8 } );9}, [] );10
Cuando usamos per_page: -1
lo que estamos haciendo es decirle a WordPress que queremos consultar todos los registros. Esto puede llegar a ser problemático si tenemos por ejemplo una red de blogs con cientos (o miles) de usuarios.
Pero generalmente, ese no es el caso así que para propósitos de este tutorial asumiremos que es seguro utilizarlo.
Si hacemos un console.log
con el contenido de records
notaremos que eventualmente tendremos lo siguiente:
1[2 {3 "id": 1,4 "name": "admin"5 }6]7
Esto es casi lo que necesitamos, ¿por qué "casi"? porque el formato es erróneo, al ver la documentación de SelectControl
encontramos que cada opción debe ser un objeto con un label
, y un value
. En este caso nuestro value
(lo que vamos a actualizar en los atributos del bloque) va a ser el ID de usuario, mientras que el label
va a ser el nombre del usuario.
Así que para conseguirlo debemos hacer un pequeño loop a través de los resultados, y ya que estamos en esto utilizaremos useMemo
para que quede guardado en la memoria y no se tenga que repetir hasta que tengamos nuevos resultados.
Primero importamos la función al inicio del archivo:
1import { useMemo } from '@wordpress/element';2
Y justo en seguida de nuestra consulta, convertimos el formato a lo que necesitamos:
1const records = useSelect( ( select ) => {2 const { getUsers } = select( coreStore );34 return getUsers( {5 per_page: -1, // Seleccionar a todos los usuarios.6 _fields: 'id,name', // Solo regresa el ID, y el Nombre.7 context: 'view', // Indica que solo queremos ver los datos, no editarlos. Esto reduce los campos a sólo lo que necesitemos.8 } );9}, [] );1011const users = useMemo( () => {12 const fetchedUsers = ( records ?? [ { id: '', name: __( 'Cargando…', 'mah-users' ) } ] ).map( ( record ) => {13 return {14 value: record.id,15 label: record.name,16 };17 } );1819 return fetchedUsers;20}, [ records ] );21
Si una vez más intentamos un console.log
, lo que veremos será el formato que necesitamos, ahora simplemente reemplazamos las opciones que teníamos en SelectControl
por nuestra variable users
:
1[2 {3 "value": 1,4 "label": "admin"5 }6]7
1<SelectControl2 label={ __( 'Selecciona un usuario', 'mah-users' ) }3 value={ 'user1' }4 options={ users }5/>6
Y el resultado será el siguiente:

Si queremos tener una mejor idea que cómo se vería esto con un nombre real, sólo debemos editar el perfil de usuario y agregar nuestros datos.
Si queremos saber cómo funcionaría con más usuarios, hay una forma sencilla de conseguirlo. wp-env
viene con una versión de wp-cli
lista para utilizarse, y como se menciona en mi Introducción a WP-CLI, hay un comando que nos permite agregar nuevos usuarios fácilmente. Necesitamos crear un archivo CVS con una lista de usuarios, por ejemplo users.cvs
en la raíz de nuestra carpeta mah-users
:
1user_login,user_email,display_name,role2bobjones,bobjones@example.com,Bob Jones,contributor3newuser1,newuser1@example.com,New User,author4existinguser,existinguser@example.com,Existing User,administrator5johndoe,johndoe@example.com,John Doe,subscriber6janedoe,janedoe@example.com,Jane Doe,subscriber7
Ahora lo guardamos y utilizamos el siguiente comando en la terminal:
1npx wp-env run cli wp user import-csv wp-content/plugins/mah-users/users.csv2
Después de agregar algunos usuarios extra a nuestro sitio, ahora nuestro resultado es el esperado:

PASO 3: GUARDANDO LA SELECCIÓN
Guardar la selección es de hecho bastante sencillo, como ya agregamos el atributo en el que guardaremos la selección al principio de este tutorial, sólo necesitamos agregar una función al prop
onChange
de SelectControl
(mucho buzzword…).
Primero especificamos que vamos a utilizar los props
attributes
, y setAttributes
en la función Edit
de nuestro bloque:
1export default function Edit( { attributes, setAttributes } ) {2
Después reemplazamos el value
por el atributo userId
y agregamos una función para que cuando el valor cambie, se actualice el atributo por el valor seleccionado… algo difícil de explicar pero básicamente se verá así en código:
1<SelectControl2 label={ __( 'Select a user', 'mah-users' ) }3 value={ attributes.userId }4 options={ users }5 onChange={ ( userId ) => setAttributes( { userId: parseInt( userId, 10 ) } ) }6/>7
¿parseInt
?
En el ejemplo anterior utilizo parseInt
para convertir el nuevo valor a un entero, esto porque comencé a tener problemas con que el valor no se guardaba.
La razón era que estaba intentando guardarse como un string
cuando en el attributo especificamos que éste iba a ser un number
.
Finalmente, podemos probarlo al seleccionar un usuario del dropdown, guardamos el post y si recargamos la página, deberíamos ver el usuario que elegimos aparecer automáticamente seleccionado.
PASO 4: MOSTRAR LA INFORMACIÓN DEL USUARIO
Aquí tenemos una decisión que tomar, por una parte, podríamos terminar nuestro editor aqui (que sería totalmente aceptable) y avanzar a la parte del frontend, pero como nos preocupamos por la experiencia del usuario, ¿por qué no mostrar una vista previa al editor cuando seleccionamos a un usuario?
La idea sería:
- Mostrar el dropdown si ningún usuario ha sido seleccionado
- Mostrar una vista previa de los datos del usuario que se selecciona
- Ofrecer controles para cambiar de usuario desde la vista previa
- Ofrecer una forma de eliminar la selección y volver al dropdown
PASO 4.1: MOSTRAR EL DROPDOWN SI NINGÚN USUARIO HA SIDO SELECCIONADO
El primer paso prácticamente ya lo tenemos, ya estamos mostrando nuestro dropdown por defecto, esto, dentro de Gutenberg, es lo que conocemos como "placeholder". En práctica se muestra cuando ninguna selección ha sido hecha, y desaparece cuando algo se selecciona, pero no funciona así por defecto, así que hagámoslo funcionar:
Para comenzar, y para seguir mejores prácticas, utilizaremos el componente Placeholder
de Gutenberg desde el mismo paquete de donde importamos SelectControl
.
1import { SelectControl, Placeholder } from '@wordpress/components';2import { people } from '@wordpress/icons';3
Después, especificamos que queremos que se muestre nuestro dropdown sólo si no se ha seleccionado un usuario, y lo envolvemos en el <Placeholder />
.
1if ( ! attributes.userId ) {2 return (3 <div { ...useBlockProps() }>4 <Placeholder icon={ people } label={ __( 'Usuarios', 'mah-users' ) }>5 <SelectControl6 label={ __( 'Selecciona un usuario', 'mah-users' ) }7 value={ attributes.userId }8 options={ users }9 onChange={ ( userId ) => setAttributes( { userId: parseInt( userId, 10 ) } ) }10 />11 </Placeholder>12 </div>13 );14}1516return (17 <div { ...useBlockProps() } >18 { __( 'Se ha seleccionado un usuario', 'mah-users' ) }19 </div>20);21
Ahora, si recargamos la página veremos que como ya hemos seleccionado y guardado un usuario anteriormente, tendremos este resultado:

Para ver nuestro placeholder, sólo necesitamos seleccionar el block, eliminarlo, e insertar uno nuevo:

Notarás que estamos importando un ícono para mostrar en nuestro placeholder, si quieres saber cuales están disponibles puedes darte una vuelta por mi Buscador de íconos de Gutenberg
Paso 4.2 MOSTRAR UNA VISTA PREVIA DE LOS DATOS DEL USUARIO QUE SE SELECCIONA
Ahora que tenemos diferentes componentes para mostrar, debemos agregar una vista previa de los datos del usuario para que el editor sepa qué es lo que está agregando, así que para comenzar, debemos hacer un request
para recibir los datos cada vez que el usuario es seleccionado.
Para esto deberemos agregar un nuevo bloque de useSelect
que utilice userId
como dependencia, de esta forma podremos conseguir el nombre del usuario, su avatar, y su descripción.
1const { userName, userAvatar, userDescription } = useSelect( ( select ) => {2 const { getEntityRecord } = select( coreStore );3 const userInfo = getEntityRecord( 'root', 'user', attributes.userId );45 return {6 userName: userInfo?.name,7 userAvatar: userInfo?.avatar_urls?.['96'],8 userDescription: userInfo?.description,9 };10}, [ attributes.userId ] );11
Y para mostrarlo debemos reemplazar nuestro div
que contiene "Se ha seleccionado un usuario" por un bloque con los datos que acabamos de recibir:
Si no queremos meternos mucho en el tema del diseño, Gutenberg ofrece un par de componentes para ayudarnos a maquetar, que utilizaré en el siguiente ejemplo, estos son Flex
y FlexItem
Importamos los nuevos componentes:
1import { Flex, FlexItem, SelectControl, Placeholder } from '@wordpress/components';2
Y dentro de la función Edit
:
1return (2 <div { ...useBlockProps() } >3 <Flex justify='start' align='start' gap="4">4 <FlexItem>5 <img src={ userAvatar } alt={ userName } />6 </FlexItem>7 <FlexItem isBlock>8 <h3>{ userName }</h3>9 <p>{ userDescription }</p>10 </FlexItem>11 </Flex>12 </div>13);14
Notarás que lo único que vemos es el nombre, así que debemos actualizar los datos del perfil con información real (recuerda que el avatar está ligado a Gravatar), y una vez guardemos los datos podremos ver esto:

PASO 4.3: OFRECER CONTROLES PARA CAMBIAR DE USUARIO DESDE LA VISTA PREVIA
Ya tenemos nuestra vista previa, pero nos encontramos con un problema, y es que si queremos cambiar de usuario ahora, deberemos borrar y volver a crear nuestro bloque. Eso no es muy amigable, así que lo que haremos es agregar un control a nuestro sidebar para cambiar fácilmente de usuario.
Básicamente copiaremos nuestro SelectControl
y lo pegaremos en los controles, así que para eso importaremos InspectorControls
, y PanelBody
y los agregaremos junto a nuestro bloque:
1import { InspectorControls } from '@wordpress/block-editor';2import { Flex, FlexItem, SelectControl, Placeholder, PanelBody} from '@wordpress/components';3
Y justo antes de nuestra vista previa agregamos nuestro control, así que modificamos el resultado de esta forma:
1return (2 <>3 <InspectorControls>4 <PanelBody title={ __( 'Configuración', 'mah-users' ) }>5 <SelectControl6 label={ __( 'Selecciona un usuario', 'mah-users' ) }7 value={ attributes.userId }8 options={ users }9 onChange={ ( userId ) => setAttributes( { userId: parseInt( userId, 10 ) } ) }10 />11 </PanelBody>12 </InspectorControls>1314 <div { ...useBlockProps() }>15 <Flex justify='start' align='start' gap="4">16 <FlexItem>17 <img src={ userAvatar } alt={ userName } />18 </FlexItem>19 <FlexItem isBlock>20 <h3>{ userName }</h3>21 <p>{ userDescription }</p>22 </FlexItem>23 </Flex>24 </div>25 </>26);27
Y ahora podremos ver que tenemos la opción de cambiar de usuario sin necesidad de eliminar nuestro bloque:

A grandes rasgos, InspectorControls
es un portal que automáticamente coloca lo que pongamos dentro en el sidebar activo para el bloque que estamos editando, esto es útil ya que nos permite colocar todos los componentes de un bloque en el mismo lugar, en lugar de tener que modificar varios archivos relacionados.
PASO 4.4: OFRECER UNA FORMA DE ELIMINAR LA SELECCIÓN Y VOLVER AL DROPDOWN (OPCIONAL)
Este último paso es completamente opcional porque ya estamos ofreciendo una forma de cambiar de usuario, pero quería mostrar una forma de reiniciar el dropdown y poder volver a escoger un usuario.
La parte funcional es bastante simple de hecho, lo único que hay que hacer es asignar un valor nulo al atributo, y para ello añadiremos un botón justo a un lado de nuestros InspectorControls
.
Primero importamos los componentes:
1import { InspectorControls, BlockControls } from '@wordpress/block-editor';2import { Flex, FlexItem, SelectControl, Placeholder, PanelBody, ToolbarGroup, ToolbarButton } from '@wordpress/components';3
Y simplemente agregamos el botón que importamos dentro del componente BlockControls
:
1<InspectorControls>2// …3</InspectorControls>45<BlockControls group="block">6 <ToolbarGroup>7 <ToolbarButton8 icon={ closeSmall }9 title={ __( 'Eliminar selección', 'mah-users' ) }10 onClick={ () => setAttributes( { userId: null } ) }11 />12 </ToolbarGroup>13</BlockControls>14
Y sólo con eso, podremos ver un nuevo botón aparecer cuando seleccionamos el bloque, al presionarlo veremos como la selección es eliminada y regresamos al inicio:

Al igual que InspectorControls
, BlockControls
funciona como un portal.
CONCLUSIÓN
Eso es todo por este tutorial (que como de costumbre se largó un poco más de lo esperado 😅️). Lo único que nos quedaría hacer sería pedir la información en PHP cuando mostremos el bloque en el frontend.
LEER MÁS
- Cómo añadir un metabox en React a Gutenberg
- Introducción a WP-CLI
- Buscador de iconos de Gutenberg
- Crear Bloque
- Creando un ambiente local para WordPress con WP-ENV
- Documentación de
SelectControl
- Portales
- Documentación de
Flex
- Documentación de
FlexItem
- Documentación de
ToolbarGroup
- Documentación de
ToolbarButton
- Gravatar