Building a WordPress block editor app? You’ll likely need to manage state — like storing user inputs or tracking changes. This might sound tricky, but WordPress gives you a super useful tool: the data package!
Think of it like a smart notebook. It lets you write things down, look them up later, and even react when something changes. Cool, right?
🎩 What is the WordPress data package?
The WordPress data package is a set of tools that handle app state inside the Gutenberg editor. It’s like React’s Context or Redux, but made for WordPress.
It helps you:
- Store data (like settings or user choices).
- Read data from your store anywhere in the app.
- Update data and trigger UI updates automatically.
The main player is @wordpress/data
. It lets you create, access, and manage “stores” of state.
🧠 Create a simple store
Here’s how to create your own custom store.
import { registerStore } from '@wordpress/data';
const DEFAULT_STATE = {
counter: 0,
};
const store = registerStore( 'myplugin/counter', {
reducer( state = DEFAULT_STATE, action ) {
switch ( action.type ) {
case 'INCREMENT':
return { ...state, counter: state.counter + 1 };
default:
return state;
}
},
actions: {
increment() {
return { type: 'INCREMENT' };
},
},
selectors: {
getCounter( state ) {
return state.counter;
},
},
} );
This store keeps track of a number. We can increase it with increment()
.
🔍 Read the state with selectors
Now that we have a store, let’s read from it.
Use the useSelect
hook like this:
import { useSelect } from '@wordpress/data';
const MyComponent = () => {
const counter = useSelect( ( select ) => {
return select( 'myplugin/counter' ).getCounter();
}, [] );
return <p>Counter is at: { counter }</p>;
};
The magic here is that useSelect
will re-render the component every time the counter changes. Zero hassle!
⚡ Change state with actions
Want to let the user click a button to increment the counter?
Use useDispatch
:
import { useDispatch } from '@wordpress/data';
const MyButton = () => {
const { increment } = useDispatch( 'myplugin/counter' );
return <button onClick={ increment }>Add one!</button>;
};
Pretty easy! This updates the store, and any component using useSelect
will update automatically.
🛠️ Real use-cases
So when would you use this in real life? Here are some ideas:
- Track form field values.
- Manage tabs or pages in a settings screen.
- Sync editor UI with background options.
- Re-use data across multiple blocks.
Anytime you need a shared state that survives beyond one component — the data package is your friend.
👀 What about built-in stores?
WordPress comes with many pre-built data stores. You can select and dispatch from them too!
Example: Want to get the current post title?
const title = useSelect( ( select ) => {
return select( 'core/editor' ).getEditedPostAttribute( 'title' );
}, [] );
That’s it — no digging through props!
📦 Tips for happy state handling
- Namespaced store names like
myplugin/myfeature
. - Separate logic (selectors, actions) from UI.
- Use selectors to avoid directly touching state.
- Only create state you need! Don’t overdo it.
The data package helps keep things predictable. You know what happened and where it happened. Debugging becomes easier — and that’s always a win!
🎉 Ready to build smarter apps?
The WordPress data package is powerful and fun once you get the hang of it. Start small. Create a counter. Move on to forms or block syncing.
And before you know it, you’ll be building pro-level interfaces that feel fast, smooth, and joyful to use!