Topics

On this page

Last updated on Oct 18, 2024

State management in Gutenberg

State management in Gutenberg is centered around Redux, the JavaScript library used to handle application state. Gutenberg uses a structured approach to manage the various states within the editor interface, such as blocks, editor settings, and post data, through a system of stores, selectors, and actions.

State management

state management in Gutenberg allows developers to track, modify, and retrieve the state of the editor and its components using a structured approach based on Redux. Selectors fetch the state, actions update it, and middleware handles asynchronous operations, all of which are integrated into a real-time, responsive user experience.

Overview

The WordPress Data API is used to manage the global application state within the editor. It serves as an abstraction over the Redux library, a popular state management solution.

Understanding Redux API Design

In both Redux and the WordPress Data API, the concept of a Store is central. The store holds the global state, which can only be modified through actions. These actions are processed by reducers, which then define how the state evolves. To read the state, you can subscribe to the store and access the current state whenever it updates.

Simplifying the Redux API Design

Key Concepts and Terminology:

WordPress Data Stores

The WordPress editor utilizes multiple stores rather than one global store, each designed for different parts of the site. Stores can be accessed using their namespace or imported directly from their respective packages.

coreWordPress Core DataInteract with global settings and core data.
core/blocksBlock Types DataManage registered blocks and styles.
core/block-editorBlock Editor DataControl the block editor, such as inserting or removing blocks.
core/editorPost Editor DataRetrieve information about the current post, such as post type or attributes.
core/edit-postEditor UI DataManage the editor’s interface, toggling various UI components.
core/noticesNotices DataManage notices within the editor.

Working with Stores

You can interact with a store either by dispatching an action (to update the state) or by selecting data from it. To do so, you need to know the store’s namespace, or you can import it from the @wordpress/ package.

import { store } from '@wordpress/...';
import { store as packageStore } from '@wordpress/package';

When importing multiple stores, a common convention is to rename the store with a relevant name.

import { useDispatch } from '@wordpress/data';
import { store as packageStore } from '@wordpress/package';
const { doSomething } = useDispatch(packageStore);

Dispatching actions to update the store can be done through the useDispatch hook:

import { useSelect } from '@wordpress/data';
import { store as packageStore } from '@wordpress/package';
const something = useSelect((select) => select(packageStore).getSomething());

To select data from a store, use the useSelect hook:

import { useSelect } from '@wordpress/data';

import { store as packageStore } from '@wordpress/package';

const { something, somethingElse } = useSelect((select) => {

    const { getSomething, getSomethingElse } = select(packageStore);

    return {

        something: getSomething(),

        somethingElse: getSomethingElse()

    };

});

For cases where you need multiple values from the same store, group them within a single useSelect call:

Handling Loading and Error States

You can determine whether a select call has been completed using the hasFinishedResolution selector, available in all core stores. This method requires the selector name as its first parameter and any parameters passed to the selector as the second.

Example:

import { useSelect } from '@wordpress/data';

import { store as packageStore } from '@wordpress/package';

const something = useSelect((select) => {

    const { getSomething, hasFinishedResolution } = select(packageStore);

    const params = ['exampleParam'];

    return {

        something: getSomething(...params),

        hasResolvedSomething: hasFinishedResolution('getSomething', params)

    };

});

Data API vs. REST API

While the Data API leverages the REST API behind the scenes, it behaves differently. Data manipulated through the Data API is only saved when the post is explicitly saved. In contrast, direct interactions with the REST API modify and persist data immediately. This makes the Data API the better option for handling post-related data within the editor environment.

 Examples of Using the Data API

Note: The useSelect and useDispatch hooks should only be used inside React components. Outside of React components, the select, dispatch, and subscribe functions from @wordpress/data can be used instead.

1. Retrieving the current post type and selected post template:

import { useSelect } from '@wordpress/data';

import { store as editorStore } from '@wordpress/editor';

const { postType, template } = useSelect((select) => ({

    postType: select(editorStore).getCurrentPostType(),

    template: select(editorStore).getEditedPostAttribute('template'),

}));

2. Inserting a block if it doesn’t already exist:

import { useSelect, useDispatch } from '@wordpress/data';

import { store as blockEditorStore } from '@wordpress/block-editor';

import { useEffect } from '@wordpress/element';

import { createBlock } from '@wordpress/blocks';

const { insertBlocks } = useDispatch(blockEditorStore);

const blocks = useSelect((select) => select(blockEditorStore).getBlocks());

useEffect(() => {

    const blockExists = blocks.some((block) => block.name === BLOCK_NAME);

    if (!blockExists) {

        insertBlocks(createBlock(BLOCK_NAME));

    }

}, [blocks]);

3. Reading and updating post meta values:

import { useSelect, useDispatch } from '@wordpress/data';

import { store as editorStore } from '@wordpress/editor';

const { editPost } = useDispatch(editorStore);

const meta = useSelect((select) => select(editorStore).getEditedPostAttribute('meta'));

function setMetaValue(key, value) {

    editPost({

        meta: { [key]: value }

    });

}

This guide provides a clear understanding of how to interact with the WordPress Data API, including accessing and updating state, handling multiple stores, and managing loading states.


Contributor

Utsav Patel

Utsav

Utsav Patel

Software Engineer