WP_Query and the WordPress Block Editor (Gutenberg)

If you are new to writing plugins for the WordPress Block Editor (Gutenberg), you may be a little confused how to do all the things you did regularly, like grabbing posts with WP_Query.

You will be very pleased to know that you can pretty much still do everything you used to do with WP_Query by using getEntityRecords.

For example, we can grab the latest posts by using the following bit of code:

wp.data.select( 'core' ).getEntityRecords( 'postType', 'posts' );

You can also query Custom Post Types (CPT) in the same way, as long as you have made your CPT accessible via the REST API.

wp.data.select( 'core' ).getEntityRecords( 'postType', 'my_custom_post_type' );

We can even pass in some arguments that may look sort of familiar:

wp.data.select( 'core' ).getEntityRecords(
	'postType', 
	'post', 
	{
        'status': 'draft', 
		'per_page': 2, 
	} 
);

Looking around, I haven’t found a definitive guide for these parameters in the documentation as yet, but looking at the codebase the ones that I have found to work are:

  • context
  • exclude
  • hide_empty
  • include
  • offset
  • order
  • orderby
  • page
  • per_page
  • post
  • search
  • slug

Try it in the Console

If you are logged into a site, and you are viewing the front end, you can test out pretty much any Gutenberg command. WordPress stores them all in the handy wp object.

Typing the above command into the console on one of my development sites I get the following:

Using getEntityRecords
Using getEntityRecords to grab posts in the Console

The screenshot above shows the console returning two WordPress post objects in the JavaScript, which are draft posts (as per the parameters I passed into getEntityRecords).

The JavaScript Post Object

Exploring the post object further in the console you can see there are plenty of properties returned for you to access.

id: 42
date: "2020-03-21T14:02:00"
date_gmt: "2020-03-21T14:02:00"
guid: {
	rendered: "https://wholesomecode.ltd/?p=42"
	raw: "https://wholesomecode.ltd/?p=42"
}
modified: "2020-03-21T14:02:00"
modified_gmt: "2020-03-21T14:02:00"
password: ""
slug: "wp-query-and-the-wordpress-block-editor-gutenberg"
status: "draft"
type: "post"
link: "https://wholesomecode.ltd/?p=42"
title: {
	raw: "WP_Query and the WordPress Block Editor (Gutenberg)"
	rendered: "WP_Query and the WordPress Block Editor (Gutenberg)"
}
content: {
	raw: "Content goes here."	
	rendered: "<p>Content goes here.</p>↵"
	protected: false
	block_version: 0
}
excerpt: {
	raw: ""
	rendered: "<p>Content goes here.</p>↵"
	protected: false
}
author: 1
featured_media: 101
comment_status: "open"
ping_status: "open"
sticky: false
template: ""
format: "standard"
meta: {
	_wcltd_meta_example_1: "1" 		
	_wcltd_meta_example_2: "Hello"
}
categories: [1]
tags: []
country: []
region: []
city: []
permalink_template: "https://wholesomecode.ltd/%postname%/"
generated_slug: "wp-query-and-the-wordpress-block-editor-gutenberg"

Post Meta in Gutenberg

One thing you will notice from the post object we explored above, is that all of the post meta is contained within the object in the meta property. This saves us doing the equivalent of get_post_meta() in Gutenberg.

Get the Featured Image with Gutenberg

Note that in the above post object you can get the featured media ID, which is stored in the featured_media property.

You can get the featured image using this by using the getMedia function, like so:

wp.data.select('core').getMedia('101');

Here it is in the console:

Using getMedia
Using getMedia in the console.

We can explore the image object that is returned in the console, and see that we can grab all the data, alt text, meta and image sizes that we need to display the image.

Note that the image sizes in the example data below have been abbreviated, otherwise it goes on for quite a bit.

id: 101
date: "2020-03-21T14:02:00"
date_gmt: "2020-03-21T14:02:00"
guid: {
	rendered: "https://wholesomecode.ltd/wp-content/uploads/2020/03/Code-Example.png"
	raw: "https://wholesomecode.ltd/wp-content/uploads/2020/03/Code-Example.png"
}
modified: "2020-03-21T14:02:00"
modified_gmt: "2020-03-21T14:02:00"
slug: "code-example"
status: "inherit"
type: "attachment"
link: "https://wholesomecode.ltd/code-example/"
title: {
	raw: "Code Example"
	rendered: "Code Example"
}
author: 1
comment_status: "closed"
ping_status: "closed"
template: ""
meta: {
	_wcltd_meta_example_1: "1" 		
	_wcltd_meta_example_2: "Hello"
}
permalink_template: "https://wholesomecode.ltd/wp-content/uploads/2020/03/Code-Example.png/?attachment_id=101"
generated_slug: "code-example"
description: {
	raw: "Code Example"
	rendered: "..."
}
caption: {
	raw: "Code Example"
	rendered: "<p>Code Example</p>↵"
}
alt_text: "Code Example"
media_type: "image"
mime_type: "image/png"
media_details: {
	width: 2310
	height: 1400
	file: "2020/03/Code-Example.png"
	sizes: {
		...
        large: {
			file: "Code-Example-1024x621.png"
			width: 1024
			height: 621
			mime_type: "image/png"
			source_url: "https://wholesomecode.ltd/wp-content/uploads/2020/03/Code-Example-1024x621.png"
        }
	}
	image_meta: {
        aperture: "0"
		credit: ""
		camera: ""
		caption: ""
		created_timestamp: "0"
		copyright: ""
		focal_length: "0"
		iso: "0"
		shutter_speed: "0"
		title: ""
		orientation: "0"
    }
}
post: null
source_url: "https://wholesomecode.ltdwp-content/uploads/2020/03/Code-Example.png"

Using it within a Block

Lets expand the block created by the @wordpress/create-block script, that I wrote about previously to include an example of how to make the equivalent of a WP_Query loop in Gutenberg.

First we need to import the select() function from wp-data. We can do this by either referencing the NPM module:

import { select } from '@wordpress/data;

Or by using the wp object:

const { select } = wp.data;

We are going to stick with the practices used in the created block and use the NPM module, and use the @wordpress/data method.

Here is a basic implementation of the equivalent of a WP_Query loop in Gutenberg:

import { registerBlockType } from '@wordpress/blocks';
import { select, withSelect } from '@wordpress/data';
import { __ } from '@wordpress/i18n';

registerBlockType( 'wcltd/wholesome-plugin', {
	title: __( 'Wholesome Plugin', 'wcltd' ),
	description: __( 'Just an Example Plugin', 'wcltd' ),
	category: 'common',
	icon: 'smiley',

	edit: withSelect( ( select ) => {
		const posts = select( 'core' ).getEntityRecords( 'postType', 'post', { 'per_page': 2 } );
		let media = {};
		posts.forEach( post => {
			media[ post.id ] = select('core').getMedia( post.featured_media );
		});
		return {
			posts,
			media
		};
	} )( props => {

		const { media, posts } = props;

		if ( ! posts || ! media ) {
			return (
				<p>{ __( 'Loading...', 'wcltd' ) }</p>
			);
		}

		return (
			<ul>
			{ posts.map(
				( post ) => {
					if ( media[ post.id ] ) {
						const imageThumbnailSrc = media[ post.id ].media_details.sizes.thumbnail.source_url;
					return (
						<li>
							<img src={ imageThumbnailSrc } />
							<a href={ post.link }>
								{ post.title.raw }
							</a>
						</li>
					)
					}
				}
			) }
			</ul>
		);
	} ),

	save() {
		return (
			<p>
				{ __( 'Wholesome Plugin – Nothing to see here.', 'wcltd' ) }
			</p>
		);
	},
} );

Note the use of withSelect to pre-load the data before the block loads. You can find out more about withSelect by reading the Gutenberg documentation.

The above code outputs the following (very basic) example of an article list and their associated thumbnails in the editor:

Example Post Loop in Gutenberg
Example Post Loop in Gutenberg.

By Matt Watson

Wordpress Developer for Hire. Developer, Father, Husband, Blogger - I do great things on the Web.