Finding wp.data selectors across stores

I’ll admit that I struggle to remember which selector lives inside which store while writing WordPress block editor code. isEditorSidebarOpened lives in the “core/edit-post” store, while getCurrentPostType is accessible via the “core/editor” store, and so on. There’s admittedly a logic to it, but it still takes a moment or two to figure out which store to use when reaching for an infrequently-needed function. That pause frequently ends up breaking my flow while working on a feature or bugfix.

Unlike finding things in the WordPress block editor globals, there doesn’t even appear to be a clearly-accessible list of stores—no wp.data.storeList array that we can loop over to build a finder-function like the one I use when trying to find a component within the wp object. The list of stores is finite, however, and unlikely to change regularly. So, in a similar spirit to my earlier post, here’s a snippet of a function I use to findSelector() by name:

( () => {
    const stores = [
        'core',
        'core/block-directory',
        'core/block-editor',
        'core/blocks',
        'core/data',
        'core/edit-post',
        'core/edit-widgets',
        'core/editor',
        'core/interface',
        'core/notices',
        'core/nux',
        'core/rich-text',
    ];

    const allSelectors = stores.reduce( ( allSelectors, store ) => {
        const storeSelectors = Object.keys( wp.data.select( store ) || {} );
        if ( ! storeSelectors.length ) {
            return allSelectors;
        }
        return allSelectors.concat(
            storeSelectors.map( ( selector ) => ( { store, selector } ) )
        );
    }, [] );

    const formatStoresForOutput = ( stores ) => stores
        .map( ( { store, selector } ) => `select( '${ store }' ).${ selector }()` )
        .join( '\n' );

    const findSelector = ( name ) => {
        const lowerName = name.toLowerCase();
        const matchingSelectors = allSelectors
            .filter( ( { selector } ) => selector.toLowerCase().indexOf( lowerName ) > -1 );
        const fuzzyRE = new RegExp( lowerName.split( '' ).join( '.*' ), 'i' );
        const fuzzyMatchingSelectors = allSelectors
            .filter( ( { selector } ) => fuzzyRE.test( selector ) )
            .filter( ( selector ) => ! matchingSelectors.includes( selector ) );
        return formatStoresForOutput( matchingSelectors.concat( fuzzyMatchingSelectors ) );
    };

    window.allSelectors = formatStoresForOutput( allSelectors );
    window.findSelector = findSelector;
} )();

Paste this into your console and it will add two objects to the global window object: an array allSelectors of string listings for each available store-selector combination, and a function findSelector that takes a string and prints out any matching selectors. It’s case-insensitive and supports fuzzy matching, so you can for example search for “getpoTyp” and it will include getPostType.

Do you have similar tricks for remembering where to find what you’re looking for within Gutenberg modules? Is there a better way to do what I’m trying to accomplish here? Let me know!

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.