Creating a Custom Store

With gratitude to Darren Ethier’s series on registering a custom store, here’s the why and how to register a custom store.

Why (and when) we need a custom store

On the latest version of the Choctaw Print site, I ran into a problem: users may choose a post from the work CPT to highlight on a page and also include a query loop of all work posts. Because blocks live in isolation, there was a world where the same post could featured 3 times on a page:

  • A two-column layout using the custom Featured Work post where both blocks feature the same post, “Project 1.”
  • The custom query block Work Gallery that shows the work posts would include “Project 1” as well.

Unlike building with PHP, where you always know what’s going to be on a page, blocks are rendered on-demand. To highlight this, here’s a sample:

<?php
// some pseudo-code as an example.
// imagine this is part of larger php file.

$featured_posts = [];
while (have_rows('posts_to_feature') {
  the_row();
  $featured_posts[] = get_sub_field('featured_post');
}

$args = array(
  'post_type'    => 'work',
  'post__not_in' => $featured_posts
);

$work_posts = new WP_Query($args);
// show the posts...

In this example, we (the devs) know which posts are featured and which to exclude because we can just grab the ACF fields (that are probably required).

The block editor inverts this power: the $featured_posts array will only exist if the Featured Work block exists on the page, but the Work Gallery block has no way of knowing what blocks exist around it.

How the Store is Registered and Used

Any time a Featured Work block gets rendered to the page, we want it to add a post id to a custom store so that other instances of the Featured Work block and the Work Gallery block can know which IDs are already in use on the page.

I won’t get into the nuts and bolts of building the store, but here’s a link to what I did for the Choctaw Print site where you can read the code for yourself.

While we’re building a WordPress flavored Redux store, this is simple enough that if you’re familiar with React’s Context + reducer API, it should make sense.

An overview of store.ts

  1. Create a custom store with createReduxStore, passing it the store namespace and an object of args.
    • the reducer and actions are stored in their own files (a WordPress convention) because I wasn’t sure if it would need to grow or not. These files are small enough on their own for this to be unnecessary.
  2. Register the store to WordPress with register.

Using the store

The Featured Work block uses the store in two ways: it gets current posts (if any) from the Set and it also gets the addPost action to (you guessed it) add a post to the set. This functionality is abstracted into a custom hook for cleaner separation of concerns; you can see the relevant code at lines 23-29 on Github.

The Work Gallery block uses the store to get current posts (if any) in the store and immediately updates the block’s attributes (so the data can be consumed on the php side). Again, this functionality is abstracted into a custom hook (relevant code is on lines 12–22). The IDs in the store are saved to the block’s excludedIds attribute and immediately consumed in the render template of the block (line 12).

See something inaccurate?