Using useSelect in Gutenberg to fetch data from the REST API

This blog post is sponsored by my WordPress and design agency Say Hello.

The WordPress Gutenberg method allows us to wrap a component in a React Higher Order Component, which adds functionality or adds data to the props of the wrapped component. But sometimes, all we need is a simpler method of just fetching some data — e.g. posts — from the REST API and then rendering the component using these posts.

withSelect and HOC is very powerful, but there’s an easier way: the useSelect method. We can insert this method call directly in our component and render the component depending on whether the data is available or not. This makes the code much leaner and much more maintainable for developers with less experience. This solution is also a great deal easier to copy and paste for reuse across many components.

I’ve used the technique in the edit component of a WordPress Gutenberg Block today, in which I need to create a SelectControl to allow the user to select a page. (I’ve since modified the interface to output a TreeSelect component instead of a SelectControl, but that adds more complexity that is unnecessary for this blog post.)

import { InspectorControls } from "@wordpress/block-editor";
import { Fragment, PanelBody, SelectControl, Spinner } from "@wordpress/components";
import { useSelect } from "@wordpress/data";
import { _x } from "@wordpress/i18n";

const Edit = props => {
    const { attributes, setAttributes } = props;

    const { post_id } = attributes;

    // The value of 'posts' will be false until the REST API responds asynchronously
    const { posts } = useSelect(select => {
        return {
            posts: select("core").getEntityRecords("postType", "page", {
                per_page: 100,
                order: "asc",
                order_by: "menu_order",

    const options = [];

    // Make an array from the REST API response if posts are available
    if (!!posts) {
        Object.values(posts).forEach(post => {
                label: post.title.rendered ? post.title.rendered : _x('No title', 'SelectControl option label', 'sha'),

    return (
                <PanelBody title={_x("Settings", "PanelBody title", "sha")}>
                    {!posts && <Spinner />}
                    {!!posts && (
                                "Select a page",
                                "SelectControl label",
                            onChange={post_id => setAttributes({ post_id })}

export default Edit;

Addendum 6th February: if you’re only getting a single dataset, you can simplify the usage of useSelect in the example above by directly assigning the result of the API call to the posts constant.

const posts = useSelect(select => {
    return select("core").getEntityRecords("postType", "page", {
        per_page: 100,
        order: "asc",
        order_by: "menu_order",

Addendum 29th July: if you’re also looking to update data on the server using this non-TOC method, then you can use the editPost method from useDispatch in a similar way. (In the example, the handleMetaValueChange callback would be used when e.g. a SelectControl change event is fired.)

const { editPost } = useDispatch('core/editor');

const handleMetaValueChange = (main_offset) => {
	editPost({ meta: { main_offset } });

Discover more from Permanent Tourist

Subscribe to get the latest posts sent to your email.