最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Use useSelectuseDispatch instead of withSelectwithDispatch

programmeradmin1浏览0评论

I've built a Featured Gallery component for Gutenberg that uses the withSelect and withDispatch higher order components to store the selected images in a meta field. I'm wondering if this code can be converted to use the useSelect and useDispatch hooks instead to simplify it. Is it possible? I tried to do it myself reading the almost useless Gutenberg docs with no success. Any help would be appreciated.

/**
 * WordPress dependencies
 */
const { __ } = wp.i18n;
const {
    BaseControl,
    Button
} = wpponents;
const { compose } = wppose;
const { withSelect, withDispatch } = wp.data;
const { MediaUpload, MediaUploadCheck }  = wp.blockEditor;

/**
 * Internal dependencies
 */
import FeaturedGalleryImage from './featured-gallery-image';

const ALLOWED_MEDIA_TYPES = [ 'image' ];

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

    const hasImages = !! featuredGalleryIds.length;

    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>            
    );
}

const applyWithSelect = withSelect( ( select ) => {
    const { getPostType } = select( 'core' );
    const { getCurrentPostId, getEditedPostAttribute } = select(
        'core/editor'
    );
    const meta = getEditedPostAttribute( 'meta' );
    const featuredGalleryIds = meta._featured_gallery;
    
    return {
        currentPostId: getCurrentPostId(),
        postType: getPostType( getEditedPostAttribute( 'type' ) ),
        featuredGalleryIds,
    };
} );

const applyWithDispatch = withDispatch( ( dispatch ) => {
        const { editPost } = dispatch( 'core/editor' );
        return {
            onUpdateGallery( images ) {
                const items = images.map( ( item ) => item.id );
                const meta = { _featured_gallery: items };
                editPost( { meta } );
            },
            onClearGallery() {
                const meta = { _featured_gallery: [] };
                editPost( { meta } );
            }
        };
    }
);

export default compose(
    applyWithSelect,
    applyWithDispatch,
)( FeaturedGallery );

I've built a Featured Gallery component for Gutenberg that uses the withSelect and withDispatch higher order components to store the selected images in a meta field. I'm wondering if this code can be converted to use the useSelect and useDispatch hooks instead to simplify it. Is it possible? I tried to do it myself reading the almost useless Gutenberg docs with no success. Any help would be appreciated.

/**
 * WordPress dependencies
 */
const { __ } = wp.i18n;
const {
    BaseControl,
    Button
} = wpponents;
const { compose } = wppose;
const { withSelect, withDispatch } = wp.data;
const { MediaUpload, MediaUploadCheck }  = wp.blockEditor;

/**
 * Internal dependencies
 */
import FeaturedGalleryImage from './featured-gallery-image';

const ALLOWED_MEDIA_TYPES = [ 'image' ];

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

    const hasImages = !! featuredGalleryIds.length;

    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>            
    );
}

const applyWithSelect = withSelect( ( select ) => {
    const { getPostType } = select( 'core' );
    const { getCurrentPostId, getEditedPostAttribute } = select(
        'core/editor'
    );
    const meta = getEditedPostAttribute( 'meta' );
    const featuredGalleryIds = meta._featured_gallery;
    
    return {
        currentPostId: getCurrentPostId(),
        postType: getPostType( getEditedPostAttribute( 'type' ) ),
        featuredGalleryIds,
    };
} );

const applyWithDispatch = withDispatch( ( dispatch ) => {
        const { editPost } = dispatch( 'core/editor' );
        return {
            onUpdateGallery( images ) {
                const items = images.map( ( item ) => item.id );
                const meta = { _featured_gallery: items };
                editPost( { meta } );
            },
            onClearGallery() {
                const meta = { _featured_gallery: [] };
                editPost( { meta } );
            }
        };
    }
);

export default compose(
    applyWithSelect,
    applyWithDispatch,
)( FeaturedGallery );
Share Improve this question edited Jan 30, 2021 at 10:45 leemon asked Jan 29, 2021 at 18:51 leemonleemon 2,0324 gold badges23 silver badges51 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 2

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
} = wpponents;
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;
发布评论

评论列表(0)

  1. 暂无评论