Manipulating Client Data in highly interactive screens in WordPress (essentially the editor page in WordPress pre 5.0.0) is not the easiest task to do for plugin authors. As much as WordPress provides a large number of functions to access and manipulate data server side, it fails at providing a consistent way to access and manipulate data on the client.

And by client side data, I refer to things like:

  • What’s the current post content in the editor? How can I update it programmatically?
  • What’s the currently selected tags/categories?
  • Is a given metabox visible or not?
  • How can I be notified if an image block is inserted into the editor of  if the user switches the post status?

Client-data is also about accessing the WordPress REST API Data client-side:

  • How do I retrieve the latest posts?
  • How do I retrieve the current user’s object?
  • How can I create a new Category?

And it can also encompass plugins data. For example:

  • How do I store/update and access my own plugins client-side data?
  • How do I access and update the content of the Yoast metabox?
  • How do I retrieve the content of ACF metaboxes in a custom ACF plugin?

Often, to address these use-cases, we had to manipulate the DOM directly: Retrieve input’s values directly from the DOM or subscribe to DOM events to ensure we’re notified properly. This often leads to hacky code and code that breaks on WordPress/plugin updates because DOM access is not an official extensibility API.

Gutenberg JavaScript-heavy World

With Gutenberg’s release coming and as we add more and more JavaScript-powered UI to WordPress pages, the need for a consistent solution to manage client-side data is urgent, we can’t rely on DOM access anymore. To address this, Gutenberg introduces the Data Module.

Retrieving Data

One of the first use-cases of the Data module is to retrieve data defined by WordPress. To do so, you need to specify the namespace of the data to call a selector on this namespace.

Here’s how we retrieve the content of the post being edited in a Gutenberg Page.

var content = wp.data.select( 'core/editor' ).getEditedPostAttribute( 'content' );

Notice that the data module API is available in the wp.data global variable. The namespace to access the editor’s data is core/editor. And in each namespace, you can use a list of selectors.

A selector is a simple JavaScript function used to retrieve client-side data. In the example above, the selector being called is getEditedPostAttribute. This selector accepts an argument corresponding to the post attribute to retrieve. If we need to retrieve the title of the post instead of its content, we can do:

var title = wp.data.select( 'core/editor' ).getEditedPostAttribute( 'title' );

Protip: The list of the available selectors/namespaces is not documented properly on WordPress/Gutenberg yet. To see the full list of the core/editor‘s selectors, you can check the selectors file here.

You can also type wp.data.select( 'core/editor' ) in your browser’s console in any Gutenberg page to inspect the full list of the selectors available in this namespace.

Updating Data

So, selectors allow us to retrieve data and similarly, each namespace can defined actions to manipulate data (create/update/remove). For example, to update the title of the post being edited in Gutenberg, you can do:

wp.data.dispatch( 'core/editor' ).editPost( { title: 'My New Title' } );

An action is a function called to update the client-data defined in a given namespace.

Protip: To see the full list of the actions defined by the core/editor namespace, you can check the actions file here.
You can also type wp.data.dispatch(  'core/editor' ) in your browser’s console in any Gutenberg page to inspect the full list of the actions available in this namespace.

Register a custom “namespace”

Plugins can also manage their client state using the data module. To achieve this, they need to register their selectors/actions in addition to a reducer to hold and update the state.

A reducer is a function describing the shape of the initial state and how the state value evolves in response to dispatched actions.

Protip: The Data module is built on-top of the redux library. Learning redux is not required to use it but taking a look at the Redux Docs and its glossary should help you master the data module.

As an example, Let’s register a custom store to keep track of a list of todo items:

// This is the reducer
function reducer( state = [], action ) {
  if ( action.type === 'ADD_TODO' ) {
    return state.concat( [ action.todo ] );
  }

  return state;
}

// These are some selectors
function getTodos( state ) {
  return state;
}

function countTodos( state ) {
  return state.length;
}

// These are the actions
function addTodo( text, done = false ) {
  return {
    type: 'ADD_TODO',
    todo: { text: text, done: done };
  };
}

// Now let's register our custom namespace
var myNamespace = 'my-todos-plugin';
wp.data.registerStore( myNamespace, { 
  reducer: reducer,
  selectors: { getTodos: getTodos, countTodos: countTodos },
  actions: { addTodo: addTodo }
} );

Now that the custom namespace is registered, we can consume this in our code, the same way we did for the core/editor’s store.

// Add a new todo item
wp.data.dispatch( 'my-todos-plugin' ).addTodo( 'Finish writing a blog post about the data module', false );

// Retrieve the list of todos
var countTodos = wp.data.select( 'my-todos-plugin' ).countTodos();

React to changes in the state

Another important use-case for WordPress Plugins often is to react to changes happening in Core Data or other plugins. To address this, the Data Module provides a subscribe function. This function allows registering listeners that get called each time the state is changed.

In the following example, we trigger some random behavior each time a new block is added to the editor:

var currentCount = wp.data.select( 'core/editor' ).getBlockCount();
wp.data.subscribe( function() {
  var newCount = wp.data.select( 'core/editor' ).getBlockCount();
  var hasNewBlocks = newCount > currentCount;
  currentCount = newCount;

  if ( hasNewBlocks ) {
    // A new block has been added, do something
    console.log( 'The new block count is :' + newCount );
  }
} );

Declarative data needs

In addition to a new way to handle data client-side, as WordPress and plugins move towards more JavaScript UIs, the use of React and its wordpress abstraction wp.element is growing.

The WordPress element module allow you to describe UI using functions (or components) taking props and returning an HTML representation of the component.

A simple component displaying an h1 can be written like so:

// You can use JSX instead of wp.element.createElement
var el = wp.element.createElement;

function Title( props ) {
  return el( 'h1', {}, props.title );
}

Very often, these UI components need data to work properly. In the example above, the Title component expects a title prop to display its content in an h1.

Let’s say we’d like to display title component using the title of the post being edited in Gutenberg, we can use the select function explained previously and do something like that:

el( Title, { title: wp.data.select( 'core/editor' ).getEditedPostAttribute( 'title' ) } );

But this approach has some downsides. The value of the title prop can change over time and we’d like to refresh our component once that happens. This means we need to use wp.data.subscribe and rerender each time the title changes.

Fortunately, to avoid having to write this logic for ourselves, The data module provides what in the React community is referred to as a Higher-order component. A Higher-order component is a function that wraps another component and feeds it with props.

Here’s how you provide the title as a prop using the data module:

var EditorPostTitle = wp.data.withSelect( function( select ) {
  return {
    title: select( 'core/editor' ).getEditedPostAttribute( 'title' )
  };
} )( Title );

Now when we render the EditorPostTitle component, it will be automatically refreshed each time the title value changes.

el( EditorPostTitle );

Similarly to how the withSelect Higher-order component provides props to components using selectors, the data module also provides a withDispatch Higher-order component to feed components with actions.

Let’s write an input that can be used to change the value of the Gutenberg’s post title.

var el = wp.element.createElement;
var compose = wp.element.compose;

function TitleInput( props ) {
  return el( 'input', { 
    value: props.title,
    onChange: function( event ) {
      props.onChangeTitle( event.target.value );
    },
  } );
}

var PostTitleInput = compose( [
  wp.data.withSelect( function( select ) {
    return {
      title: select( 'core/editor' ).getEditedPostAttribute( 'title' )
    };
  } ),
  wp.data.withDispatch( function( dispatch ) {
    return {
      onChangeTitle: function( title ) {
        dispatch( 'core/editor' ).editPost( { title: title } );
      }
    };
  } )
] )( TitleInput );

Notice in this example how we’re composing both withSelect to retrieve the current title and withDispatch to provide a onChangeTitle callback the input Component can call to perform the updates.

Protip: Notice the compose function being used in the example, it’s an utility function that allow combining several Higher-order components together. 

Learn more about this functional programming pattern here

 Fetching WordPress Data

Until now, we were mostly dealing with synchronous selectors and actions but WordPress Data offers a way to handle asynchronous data as well.

To do so, we can attach a side-effect to each selector: A function that gets executed the first time a selector is called with a given set of arguments. This function can be responsible of performing an async API request and updating the state once the request succeeds. These side-effect functions are called resolvers.

For instance, we might be interested to fetch posts list to display them in a PostList component.

var el = wp.element.createElement;

// This a UI component showing a list of post titles given a posts prop.
function PostList( props ) {
  return props.posts.map( function( post ) {
    return el( 'div', { key: post.id }, post.title.rendered );
  } );
}

var RecentPostList = wp.data.withSelect( function( select ) {
  posts: select( 'core' ).getEntityRecords( 'postType', 'post' )
} );

Notice that in this example, the APIs being used are the same we were using before, but behind the scenes, a REST API is being executed the first time the getEntityRecords selector is called, to fetch the post list.

Here’s the exact flow:

  • The first time the getEntityRecords selector is called, the post list is empty. So the PostList component is rendered with an empty list of posts.
  • But behind the scenes the core data module also calls the resolver called getEntityRecords to perform the API Request for you. 
  • When the API Request resolves, the state is updated with the received posts. This will automatically retrigger a rerender, thanks to the way withSelect works.
  • The PostList gets rerendered with the update list of posts.  

Protip: If you’re interested in implementing this kind of side effects in your own plugins, make sure to take a look at the resolvers in the Data module docs.

WordPress Headless / Agnostic?

The Data Module is a generic JavaScript package to handle data, if you want to use in a WordPress client, or if you want to use any applications not related with WordPress, that’s also possible. Instead of using the wp.data global, you can just fetch the package from npm:

npm install @wordpress/data --save

Going further

The Data Module is still being enhanced, if you’re Interested in learning more about the Data Module or any other modules, make sure to join the #core-js channel of the WordPress Core slack and the weekly meetings happening each Tuesday at 13:00 UTC.

Thanks Andrew Duthie for the feedback.


This post is brought to you by the new Gutenberg Editor 

22 thoughts on “ Efficient client data management for WordPress Plugins ”

  1. Nice work Riad
    I’ve seen a video which talk about sending data between wordpress and block that could be useful to somebody
    https://www.youtube.com/watch?v=g-y3SXeooyo
    I’ve have a question to ask you about columns
    you use InnerBlocks layouts={ getColumnLayouts( columns ) }
    Is it possible to wrap each of this columns in a component ?
    Something that could be used like this
    InnerBlocks layouts={ [
    { name: ‘column-1’, label: ‘Column 1’, icon: ‘columns’ , wrapper:’Mycomponent’},
    { name: ‘column-2’, label: ‘Column 2’, icon: ‘columns’, wrapper:’Mycomponent’ },
    ] }

    1. I know the columns block is being worked on to add wrappers, so yeah, keep an eye on the next releases.

  2. Hi, is there a way to get the attributes of a parent block within the edit function of an inner block?

    1. You can probably traverse the block hierarchy using the data module’s selectors in the `core/editor` namespace. I don’t have the selectors in mind but you should be able to grab the current’s uid from the props and access its parent block instance.

  3. Hi Riad
    Great article as usual
    I have one question about withstate internal state. If we had three richtext in a component which can change. How concatanate the three in an internal state ?
    I had a use case which may be more explicit
    I found this in a card gutenberg addons : edit: withState( { editable: ‘content’, } )( edit ).
    https://gist.github.com/sylvaincordiere/3642a97146e0f07538138f639eefebe6#file-gistfile1-txt-L423
    I suppose that editable: ‘content’ is the internal state but is the ugb-card-heading content, ugb-tagline content or ugb-card-des content. There are three richtext and I can’t understand which one is the internal state.

    1. Not certain what you mean by internal state, you can use a separate attribute per RichText.

    2. I use internal state because it’s the word use in doc : https://github.com/WordPress/gutenberg/tree/master/components/higher-order/with-state#withstate
      I guess it’s the component state.
      That’s what seems complicated to me the relation between attributes and the internal state because attribute is a react state.
      In the example above https://gist.github.com/sylvaincordiere/3642a97146e0f07538138f639eefebe6#file-gistfile1-txt-L62 it use one setState( { editable: newEditable } ) but it has three richtext

      1. Attributes should be used for the state that needs to be persisted in the post_content (across page reloads) and the `setState` or the React component state is just local state used for temporary state (for example a variable holding the selected tab or something like that)

  4. Thanks for this post Riad.
    I’ve take a look at latest post block in gutenberg.
    Is there a way to add load more button or pagination to it ?

    1. It’s certainly possible but I don’t think that’ss going to be added to the core blocks because it mirrors the current widget. But it’s totally achievable in a custom block.

  5. Riad
    As usual you learn me a lot with few paragraph.
    Few month ago you talk about the possibility of including graphql in wordpress’s future core.
    Is there any news about that ?
    Because I struggle a lot with wp rest api and I think I’m not alone.
    A simple example :
    In WordPress 4.7 the filter argument for any post endpoint was removed so if I want to filter posts to show only post with featured image it become impossible without adding another plugin which add the filter.

    1. Hi, Glad you’re learning stuff with my posts.

      So, yeah GraphQL is something we definitely keep an eye on, but at the moment Core is focused on Gutenberg. No real news in this area so but hopefully some exploration could start in the next months.

  6. Hello, Riad
    Thank you for the great article, you saved my day and I mean it :).
    Note: At “React to changes in the state” example at the condition “if ( newCount > currentCount )” it must be “if ( hasNewBlocks ) {“

  7. Hi riad
    I’ve seen withAPIData is being deprecated : https://github.com/WordPress/gutenberg/issues/7390
    I’ve try to replace it in the latest post block without success:
    edit: withSelect( ( select ) => {
    return {
    posts: `/wp/v2/posts?per_page=3`
    };
    } )( ( { posts, className, isSelected, attributes, setAttributes } ) => {
    if ( ! posts.data ) {
    return (

    { __( ‘Loading Posts’ ) }

    );
    }
    if ( 0 === posts.data.length ) {
    return (
    { __( ‘No posts’ ) }
    );
    }
    return (

    setAttributes({ content })}
    placeholder={__(‘placeholder’)}
    />

    {posts.data.map(post => {
    return (


    {post.title.rendered}

    );
    })}

    );
    } ),
    Could you give an indication about using withSelect ?

    1. you can use the `select( ‘core’ ).getPosts()` to retrieve the list of posts, but there’s no support for filtering/pagination yet, it will come soon enough.

  8. Thanks for your answer but I get TypeError: “e(…).getPosts is not a function”. I’ve search getPosts function in gutenberg doc without success. I’ve imported withSelect and select from wp.data though this was enough

    1. Oh you’re right, the function is missing for some reason. You can do this as an alternative for now `wp.data.select(‘core’).getEntityRecords( ‘postType’, ‘post’ )`

  9. Hi Riad I ‘ve notice that you recently change withAPIData by withSelect in gutenberg code. With withAPIData we can use the rest api to filter post like posts: `/wp/v2/posts?per_page=3`. How could we do that with withSelect ?

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.