I’ve been working on a block that requires the use of fetching data from the WordPress REST API in a couple of my components. The first component needing data was my PostList component. This component is responsible for displaying a list of posts in the editor as well as inside of a modal for my post picker component. The second was for fetching the categories that each post was assigned, so that I could display the category names for each post.
Thankfully the Core Data API in WordPress allows us to use the withSelect
higher order component to fetch this data and pass it to our component as props. The getEntityRecords
function allows us to fetch data to certain REST API endpoints to get back any data we want to use within our component.
There currently isn’t a documented list of entities that we’re able to query, however the Gutenberg source code provides us the default entities. Note that the widgetArea
entity is experimental as of writing. For this article we’ll focus on the postType
and taxonomy
entities.
Name | Base URL | |
site | /wp/v2/settings | |
postType | /wp/v2/types | |
media | /wp/v2/media | |
taxonomy | /wp/v2/taxonomies | |
widgetArea | /__experimental/widget-areas |
Exploring the Data API
Using your browser’s JavaScript console we can explore the WordPress Data API. The data API is exposed as the wp.data
object. If you type in wp.data.select("core")
this will access the core data API. From there we can run wp.data.select("core").getEntityRecords()
which will return an empty array. getEntityRecords
expects 4 parameters.
- state
Object
: State tree - kind
string
: Entity kind. - name
string
: Entity name. - query
?Object
: Optional terms query.
To select all of our posts in the console run: wp.data.select("core").getEntityRecords('postType', 'post', { per_page: -1 })
If you get back null the first time run it again and you’ll get back an object with all of your posts. In this case the entity kind was postType
, post
was the entity name since we wanted back that specific post type. We could have replaced that with any other post type or custom post type that was exposed on the REST API to get back those specific results. The object that we passed is the terms query. Using the REST API parameters, corresponding to their endpoints, we can filter the data we want to get back . For Post Query Parameters see the REST API Handbook. We’ll use these next as we build our basic component.
Building our Component
React has begun moving away from class based components, and in truth not every component needs to be an entire class when functional components can do everything just as well. First we need our component that we’ll pass to withSelect
and our withSelect
export.
import { withSelect } from '@wordpress/data';
const PostList = ( props ) => {
return(
// Post Info will be displayed here
)
}
export default withSelect( (select, ownProps ) => {
const { getEntityRecords } = select( 'core ');
const postQuery = {
per_page: 10,
page: 2
}
return {
postList: getEntityRecords('postType', 'post' postQuery ),
}
})(PostList)
In the above example we wrap the PostList component in a withSelect
higher order component, and use getEntityRecords
to fetch back postList
and pass that as props to the PostList
component. The postQuery
can further be modified using more parameters. If you wanted to dynamically control the parameters you could do so with attributes or passing them into the PostList component as props from a component higher up in the block.
Using Lodash Map to display data
If we were to try to render any data we got the result from the REST API, we would get some errors so we first need to verify that the data we got back is expected, and that it’s of a good length. We then will render a placeholder if we don’t have the data back, which will show the data once that select has finished.
import { map } from 'lodash';
import { withSelect } from '@wordpress/data';
import { Placeholder, Spinner } from '@wordpress/components';
import { Fragment } from '@wordpress/element';
const PostList = ( props ) => {
const { postList } = props;
const hasPosts = Array.isArray( postList ) && postList.length;
if ( ! hasPosts ) {
return (
<Placeholder
icon="excerpt-view"
label={ __( 'Post Block', '' ) }
>
{ ! Array.isArray( postList ) ? <Spinner /> : __( 'No posts found.', '' ) }
</Placeholder>
);
}
return(
<Fragment>
{
map( postList, ( post ) => {
return (
<div>{ post.title.raw }</div>
);
})}
</Fragment>
);
}
export default withSelect( (select, ownProps ) => {
const { getEntityRecords } = select( 'core ');
const postQuery = {
per_page: 10,
page: 2
}
return {
postList: getEntityRecords('postType', 'post' postQuery ),
}
})(PostList)
Conclusion
This example component should be enough to get off the ground writing your own components fetching data from the REST API. I hope that as Gutenberg grows the number of entities can grow as well to target all of the endpoints. Once I figured out how components can all fit together and power one another the new editor has become a blast to develop for. It can almost be described as a giant puzzle. I have not yet gotten a full understanding of the compose function which can help join your higher order components together, but once I do I’ll have a follow up article exploring that. I love to talk development on Twitter so if you’re up for chatting Gutenberg or React give me a shout.