Use useSelect/useDispatch instead of withSelect/withDispatch

After banging my head against Gutenberg’s wall for a few hours, I came up with something that seems to work. It uses the useSelect and useEntityProp hooks instead of the withSelect and withDispatch HOCs. The truth is that using hooks makes the code simpler and easier to understand.

/**
 * WordPress dependencies
 */
const { __ } = wp.i18n;
const {
    BaseControl,
    Button
} = wp.components;
const { useSelect } = wp.data;
const { useEntityProp } = wp.coreData;
const { MediaUpload, MediaUploadCheck }  = wp.blockEditor;

/**
 * Internal dependencies
 */

import FeaturedGalleryImage from './featured-gallery-image';

const ALLOWED_MEDIA_TYPES = [ 'image' ];

function FeaturedGallery( {
    noticeUI,
} ) {
    const instructions = (
        <p>
            { __(
                'To edit the featured gallery, you need permission to upload media.', 'my-featured-gallery'
            ) }
        </p>
    );

    const postType = useSelect(
        ( select ) => select( 'core/editor' ).getCurrentPostType(),
        []
    );

    const [ meta, setMeta ] = useEntityProp(
        'postType',
        postType,
        'meta'
    );

    const featuredGalleryIds = meta['_featured_gallery'];
    const hasImages = !! featuredGalleryIds.length;

    function onUpdateGallery( images ) {
        const items = images.map( ( item ) => item.id );
        setMeta( { ...meta, '_featured_gallery': items } );
    }

    function onClearGallery() {
        setMeta( { ...meta, '_featured_gallery': [] } );
    }

    return (
        <BaseControl
            className="my-featured-gallery"
        >
            { noticeUI }
            <div className="editor-post-featured-gallery">
                <div className="editor-post-featured-gallery__container">
                    { hasImages && (
                        <ul className="featured-gallery-grid">
                            { featuredGalleryIds.map( ( img ) => (
                                <li key={ img } tabIndex={0}>
                                    <FeaturedGalleryImage
                                        id={ img }
                                    />
                                </li>
                            ) ) }
                        </ul>
                    ) }
                </div>
                <MediaUploadCheck fallback={ instructions }>
                    <MediaUpload
                        title={ __( 'Featured gallery', 'my-featured-gallery' ) }
                        multiple
                        gallery
                        addToGallery={ hasImages }
                        onSelect={ onUpdateGallery }
                        allowedTypes={ ALLOWED_MEDIA_TYPES }
                        value={ hasImages ? featuredGalleryIds : [] }
                        render={ ( { open } ) => (
                                <Button
                                    className={
                                        hasImages
                                            ? 'editor-post-featured-gallery__edit'
                                            : 'editor-post-featured-gallery__add'
                                    }
                                    onClick={ open }
                                    isSecondary
                                >
                                    {
                                        hasImages
                                            ? __( 'Edit gallery', 'my-featured-gallery' )
                                            : __( 'Add to gallery', 'my-featured-gallery' )
                                    }
                                </Button>
                        ) }
                    />
                </MediaUploadCheck>                
                { hasImages && (
                    <MediaUploadCheck>
                        <Button onClick={ onClearGallery } isLink isDestructive>
                            { 
                                __( 'Clear gallery', 'my-featured-gallery' )
                            }
                        </Button>
                    </MediaUploadCheck>
                ) }
            </div>
        </BaseControl>            
    );
}

export default FeaturedGallery;