Search code examples
wordpress-gutenberghigher-order-componentsgutenberg-blocks

Wordpress Gutenberg Block: use wp.data.select in BlockEdit filter HOC


I am trying to extend the core/image block by pulling in the media description field and use its contents as an extra attribute. I am currently stuck with getting a Rest API call with wp.data.select('core').getMedia(id) inside the BlockEdit filter HOC to work. Whatever I've tried so far ("directly" using select like in example code below or a useSelect hook it always results in the same error "TypeError: select(...).getMedia(...) is undefined". I am successfully using core block extensions for other functionality as well as many different select calls in other custom blocks. I am importing select and useSelect from the wp.data package and I have set my dependencies in the plugins PHP.

Here's my code (relevant parts):

Top of script

const { select, useSelect } = wp.data;
const restrictTo = ['core/image'];

BlockEdit HOC – wrapping image block's Edit function

const withDescription = createHigherOrderComponent((BlockEdit) => {
    return (props) => {
        const {name, attributes, setAttributes, isSelected} = props;
        if ( isSelected && restrictTo.includes(name) ) {
            const {id} = attributes;
            // id will be available when image is chosen from the inserter
            if (id) {
                /* doesn't work, yields error described above, even with useSelect hook */
                const desc = select('core').getMedia(id).description.raw;
            }
            // 
        }
        return (
            <Fragment>
                <BlockEdit {...props} />
                <Inspector Controls stuff...>
            </Fragment>
        )
    };
}, 'withDescription');

Filter

addFilter('editor.BlockEdit','vortac/with-description',withDescription);

I have already searched for articles and help covering a similar problem and found this from the wordpress.org support forums: https://wordpress.org/support/topic/how-to-use-wp-data-select-in-blocklist/

@jorgefilipecosta is referencing a piece of Core code that is actually using selectin a HOC. It's a different BlockFilter editor.BlockListBlock though, but I don't think this should make a difference.

Thanks in advance for your help.


Solution

  • I have finally found the mistake in my code. Using select in the BlockEdit filter HOC is not the actual problem, as I assumed when posting the question. The select call itself in the form of const desc = select('core').getMedia(id).description.raw; is not correct. I suppose it doesn't work because the select call yields a promise and until a value is loaded for .getMedia() it is not possible to access the field description, resulting in the error I originally described in my question. So here's the actual simple solution in my final implementation using the useSelect hook (again just the relevant parts):

    const { select, useSelect } = wp.data;
    const restrictTo = [ 'core/image' ];
    
    const withDescription = createHigherOrderComponent( ( BlockEdit ) => {
        return ( props ) => {
            const { name, attributes, setAttributes, isSelected } = props;
            if ( isSelected && restrictTo.includes( name ) ) {
                const { id } = attributes;
                
                // an image id will be available as soon as an image is chosen from the inserter
                if ( id ) {
                    const tmpDesc = useSelect( ( select ) => {
                       return select( 'core' ).getMedia( id );
                    }, [ id ] );
                    // if a value for tmpDesc is set its raw description will be accessible
                    const desc = ( tmpDesc ) ? tmpDesc[ 'description' ][ 'raw' ] : '';
                }
                // 
            }
            return (
                <Fragment>
                    <BlockEdit {...props} />
                    <Inspector Controls stuff...>
                </Fragment>
            )
        };
    }, 'withDescription');
    
    addFilter('editor.BlockEdit','vortac/with-description',withDescription);