Back to Blog
Lesson 17 of the Intermediate WordPress Plugins: REST API & React Admin course
WordPressJune 25, 20264 min read

Understanding WordPress Data Store Architecture | @wordpress/data Guide

Master the @wordpress/data architecture. Learn how the store, selector, and action pattern provides a robust, global state for your WordPress plugins.

@wordpress/dataReduxState architectureReactWordPress Developmentwordpressphpplugin-development

Previously in this course, we explored Handling Asynchronous State in React for WordPress Plugins, where we managed local loading and error states within individual components using useState. While useState is excellent for isolated UI logic, it falls short when multiple components need to share data or when your application grows in complexity.

In this lesson, we move beyond local state and into the @wordpress/data architecture. This is the same Redux-based system that powers the WordPress block editor, providing a predictable, global state layer for your plugins.

The Problem: Why Global State is Necessary

As your plugin expands, you'll find yourself "prop drilling"—passing data down through five layers of components just to reach a child that needs it. You might also notice that when you update a piece of data in one part of your dashboard, other parts stay stale because they don't share a single source of truth.

In a standard React app, you might reach for the Context API or Redux. In WordPress, we use @wordpress/data, which provides a standardized way to implement a centralized state. It solves three critical problems:

  1. Consistency: All components see the same data at the same time.
  2. Performance: With memoized selectors, components only re-render when the specific slice of data they care about changes.
  3. Efficiency: It handles the complex logic of fetching, caching, and updating data, preventing redundant API calls.

The Store/Selector/Action Pattern

The WordPress data architecture relies on a "Store," which acts as the single source of truth. To interact with this store, we follow a strict unidirectional flow:

1. The Store

The store holds your application's state. It is a structured object where your data lives. In our Knowledge Base project, the store will hold our collection of articles.

2. Selectors (Reading)

Selectors are functions used to retrieve data from the store. Instead of accessing state directly, you call a selector. Example: select('my-plugin/kb').getArticles(). Crucially, selectors are often memoized. If the underlying data hasn't changed, the selector returns the cached result, saving precious CPU cycles.

3. Actions (Writing)

Actions are plain JavaScript objects that describe what happened (e.g., ADD_ARTICLE). You "dispatch" an action to the store. A "Reducer" then listens for that action and updates the state immutably.

4. Resolvers (Fetching)

Resolvers are a unique WordPress feature. They are functions that automatically trigger API requests when a selector is called but the data isn't in the store yet. This keeps your components clean; they just ask for data, and the store handles the network orchestration.

A Concrete Example: Accessing Core Data

You are likely already using the WordPress data layer without realizing it. When you interact with the block editor, you are querying the core data stores.

JAVASCRIPT
import { useSelect } from CE9178">'@wordpress/data';

const MyComponent = () => {
    // We use useSelect to hook into the global store
    const user = useSelect((select) => {
        return select(CE9178">'core').getCurrentUser();
    }, []);

    if (!user) return <p>Loading...</p>;

    return <h1>Welcome back, {user.name}</h1>;
};

In this example, useSelect subscribes the component to the core data store. When the user object changes, the component automatically updates. If the user data wasn't already cached, the core store's internal resolver would have fetched it from the REST API automatically.

Hands-on Exercise: Exploring the Registry

To understand how this works in your own environment, open your browser’s console on your WordPress admin dashboard (where your plugin is active) and try to inspect the data registry:

  1. Open the Developer Tools (F12).
  2. Type wp.data.select('core').getAuthors() and hit enter.
  3. Observe the returned array of authors.
  4. Now, try wp.data.dispatch('core').saveEntityRecord('postType', 'post', { title: 'Test' }).

You are now interacting with the same architecture that powers the Gutenberg editor.

Common Pitfalls

  • Direct Mutation: Never mutate state directly (e.g., state.articles.push(item)). Always use actions and reducers to return a new state object. This ensures React's change detection triggers correctly.
  • Over-Selecting: Avoid selecting the entire state tree. If you only need articles, create a selector that returns only articles. If you select the whole state, your component will re-render whenever any part of the state changes, causing performance bottlenecks.
  • Ignoring Resolvers: Don't manually trigger apiFetch inside your components if a resolver can handle it. The store’s job is to manage the lifecycle of the data; let it do its job.

Recap

The @wordpress/data architecture provides a robust, scalable way to manage state in your WordPress admin screens. By mastering the store, selector, and action pattern, you ensure your plugin behaves predictably, performs efficiently, and integrates seamlessly with the rest of the WordPress ecosystem.

Next, we will begin the process of formalizing our own data layer by registering a custom store for our Knowledge Base plugin.

Up next: Registering a Custom Data Store

Similar Posts