Selecting and Dispatching with the Data Module

When you start building web applications with React, you begin to realize that you are often passing your application’s state (or portions of the state) down to child components. Other times you are lifting state up to a common ancestor component for the child components to share. A solution to centralizing the application state is by using Redux which brings a lot of great features to make working with your application’s state easier.

The WordPress Data Module, like Redux, is used to manage application state for both plugins and WordPress. The data module is implemented on top of Redux but provides a way to create separate stores. A store is an object that holds the application’s state. You can read more about how the WordPress Data Module differs from Redux in the Gutenberg Handbook.

Gutenberg registers a handful of stores for individual modules within the application’s state by default. You can also view the reference for these data modules in the Gutenberg Handbook. We are going to build an example block that utilizing the selectors and actions of the core/editor and core/notices data modules in this walk-through.

What is a selector?

Selectors are the primary mechanism for retrieving data from the application state. For example, if we wanted to retrieve a list of all blocks from this post we would call the getBlocks() selector from the core/editor data store.

Here’s how to do it in your browser’s developer console within the Gutenberg editor.

wp.data.select('core/editor').getBlocks();

We would receive the following array containing all the block data of this post.

[
  { "clientId": "a8f90fd9-3c96-4226-b578-1a53a5adc836", "name": "core/paragraph", ... },
  { "clientId": "34208a79-7da9-4d07-89cb-3a3a54d5f7a0", "name": "core/paragraph", ... },
  { "clientId": "967498a2-1055-48e5-8d09-71bc1a40ff80", "name": "core/paragraph", ... },
  { "clientId": "bffa3517-0ca3-42be-b70d-2399c7007a57", "name": "core/heading", ... },
  { "clientId": "5113943b-75dd-4793-8ae5-2752f28955e3", "name": "core/paragraph", ... },
  { "clientId": "f692fc2f-6092-42a4-9f37-68bacd3c18ff", "name": "core/code", ... },
  { "clientId": "2f85326b-3b1c-4cfe-b328-851435043c17", "name": "core/paragraph", ... },
  { "clientId": "cf1702ea-2f08-4f01-be86-19ece86ee45a", "name": "core/code", ... },
  { "clientId": "0c09eefd-0cec-4552-be05-1aadcf0609a7", "name": "core/heading", ... },
  { "clientId": "181b4b26-b6f8-4c00-bd8e-2f1b7806fe3d", "name": "core/paragraph", ... }
]

What is an action

Actions are the primary mechanism for making changes to the application state. For this example, we can create a new notice by dispatching the createNotice() action from the core/editor data store.

Here’s how to do it in your browser’s developer console within the Gutenberg editor.

wp.data.dispatch('core/notices').createNotice( 'success', 'Here is our notice!' );

We would then see the following notice displayed directly below the editor’s top bar.

Setting up our block

In Getting Started with Block Development in ES.Next, we created a simple block with a minimal build process using webpack and Babel. In How to Internationalize Your Block, we updated our simple block with internationalization and did a little refactoring so let’s start from that. You can also grab the code from GitHub.

We need to update the wp_register_script call to include the wp-data and wp-compose dependencies.

Create our block

We’re going to put together a simple block that will display the block types in the current post and include buttons to trigger different notification types. This should give you a good starting point to explore other data stores and select or dispatch the available actions.

Let’s get started by creating a functional component, which we’ll use in our edit function, and importing our dependencies.

There are a few new functions and components we’re importing to work with the data stores: compose, withSelect, and withDispatch.

withSelect

This is a higher-order component that we use to pass data as props from the selected data store to our component.

Read more in the Gutenberg Handbook

withDispatch

This is a higher-order component that we use to pass dispatch functions as props from the selected data store to our component.

Read more in the Gutenberg Handbook

compose

This function composes multiple higher-order components into a single higher-order component. We will pass our withSelect and withDispatch function calls as parameters of compose alongside our component. Our component will then have access to the selectors and actions we define.

Read more in the Gutenberg Handbook

Write the component

Next we’ve created a component named MyComponentBase which accepts our props and renders the output of our block edit function. I’ve used variable deconstruction in the received parameters to select what we’re going to use from the props passed in. This is another cool feature of ES.Next that I love using.

We’re also creating a function to easily dispatch the createNotice action. In the returned JSX, we’re calling this function whenever one of the links are clicked.

And finally we’re creating an unordered list by looping through all the blocks passed and outputting their name.

Now that we have our component ready, it’s time to pass in our selectors and actions. Using withSelect and withDispatch we need to return an object which will be mapped to our component as props. We need one selector to retrieve all the blocks in the post and one action to dispatch our notifications.

Note that I am using another shorthand available in ES.Next to deconstruct variables from the returned dispatch('core/notices') call and at the same time returning an object containing it. This would be the equivalent:

We can get a list of all blocks in the post with the getBlocks selector of the core/editor data store. In our withSelect call we are passing the result under the blocks property. That way we can use props.blocks in our component to work with them. What is really cool is that our component will update with any blocks added or removed during editing!

We can dispatch a notification to the editor with the createNotice action of the core/notices data store. In our withDispatch call we are passing the action dispatcher under the createNotice property. We can then use props.createNotice() to dispatch the notice within our component.

Finally, let’s put it all together with compose and update our edit function within the registerBlockType call.

Activate the plugin and add the block to a post to see it in action! You should see something like this:

Conclusion

Hopefully this quick walk-through gives you a simple overview of how to interact with the data stores in Gutenberg. You should be able to explore the existing selectors and actions of the core data stores and interact with them in a similar way. In a future post we’ll tackle creating our own data stores with selectors and actions.

I’ve put all the code for this walk-through up on GitHub for reference.

Leave a Reply

Your email address will not be published. Required fields are marked *