Writing Selectors for Data Access: Memoization in WordPress
Master selectors in @wordpress/data to efficiently retrieve state. Learn to implement memoization for high-performance React admin interfaces in WordPress.
Previously in this course, we explored registering a custom data store in WordPress, which set the foundation for managing our plugin's state. In this lesson, we move from defining the store to extracting data from it, ensuring our components only re-render when the specific data they depend on actually changes.
The Role of Selectors in @wordpress/data
In the WordPress data store architecture, selectors are pure functions that take the state as an argument and return a specific slice of data.
Directly accessing the store state inside a component is an anti-pattern. If you access a large object directly, your component will re-render whenever any part of that object changes, even if the specific property you care about remains identical. Selectors solve this by acting as a bridge, transforming raw state into the exact format your UI needs.
Implementing Memoization
Because selectors run every time the store changes, they must be performant. We use memoization to cache the result of a selector based on its arguments. If the arguments haven't changed, the selector returns the cached result instead of re-calculating it.
In the WordPress data ecosystem, we typically use createSelector from the @wordpress/data package, which is built on top of the popular reselect library.
Worked Example: Retrieving Knowledge Base Items
Let's assume our Knowledge Base store holds an array of items. We want a selector that filters these items by a specific category.
JAVASCRIPTimport { createSelector } from CE9178">'@wordpress/data'; // The base selector: returns the raw items from state export const getKnowledgeBaseItems = (state) => { return state.items; }; // The memoized selector: filters items by category export const getItemsByCategory = createSelector( (state, category) => { const items = getKnowledgeBaseItems(state); return items.filter((item) => item.category === category); }, (state, category) => [state.items, category] // Dependency array );
In this example, createSelector accepts two arguments:
- The result function: The logic that computes the derived data.
- The dependency function: A function that returns an array of dependencies. If these dependencies match the previous run, the result function is skipped.
Querying Store State from Components
To use these selectors inside your React components, you use the useSelect hook. This hook automatically subscribes the component to the store and triggers a re-render when the selector's output changes.
JAVASCRIPTimport { useSelect } from CE9178">'@wordpress/data'; import { STORE_NAME } from CE9178">'./store'; const CategoryList = ({ category }) => { const items = useSelect((select) => { return select(STORE_NAME).getItemsByCategory(category); }, [category]); if (!items.length) return <p>No items found.</p>; return ( <ul> {items.map(item => <li key={item.id}>{item.title}</li>)} </ul> ); };
Hands-on Exercise
- Open your Knowledge Base store definition file.
- Implement a
getArchivedItemsselector that returns only items wherestatus === 'archived'. - Use
createSelectorto ensure this filtering logic is memoized. - Update your
Dashboardcomponent to useuseSelectand display a count of archived items in a header summary.
Common Pitfalls
- Violating Purity: Selectors must remain pure. Never perform side effects (like API calls or
console.logwith mutations) inside a selector. If you need to fetch data, use resolvers. - Over-selecting: Avoid creating one giant selector that returns the entire state object. Create granular selectors that return only what a specific component requires.
- Dependency Array Mismatch: If you forget to include a variable used in your selector logic within the dependency array of
createSelector, the selector will return stale data. - Ignoring
useSelect: Manually subscribing to the store usingsubscribeis error-prone and inefficient. Always preferuseSelect.
Selectors are the primary way your UI communicates with your data. By keeping them pure and memoized, you ensure that your admin dashboard remains responsive even as your Knowledge Base grows.
Up next: Defining Actions and Reducers to modify the store state.
Work with me

Custom WordPress Plugin Development
Custom WordPress & WooCommerce plugins built to standard โ by the developer behind a plugin with 5,000+ active installs and a SaaS with 10,000+ users.

Headless WordPress + Next.js Frontend Development
Keep WordPress for content, get a lightning-fast Next.js frontend. The best of both worlds โ familiar editing, modern speed.