1

I am using useSelect to get available image sizes and then I want to check that the images actually have these sizes as there may have been some custom image sizes added.

What I have done is working but I am concerned the implementation is incorrect as it is the first time I am using useSelect.

import { compose } from "@wordpress/compose";
import { useBlockProps } from "@wordpress/block-editor";
import { isBlobURL } from "@wordpress/blob";
import {
    MediaPlaceholder,
    BlockControls,
    MediaUpload,
    MediaUploadCheck,
    InspectorControls,
} from "@wordpress/block-editor";
import {
    Toolbar,
    IconButton,
    PanelBody,
    SelectControl,
} from "@wordpress/components";
const { useSelect } = wp.data;

export function Edit(props) {


    const blockProps = useBlockProps();
    const {
        attributes: { id, alt, url },
        setAttributes,
    } = props;

    
    const imageSizes = useSelect(
        (select) => {
            return {
                imageSizes: select("core/editor").getEditorSettings().imageSizes,
                image: id ? select("core").getMedia(id) : null,
            };
        },
        [id]
    );

    const onSelectImage = ({ id, url, alt }) => {
        setAttributes({ id, url, alt });
    };

    function getImageSizes() {
        const { image } = imageSizes;
        if (!image) return [];
        let options = [];
        const sizes = image.media_details.sizes;
        for (const key in sizes) {
            const size = sizes[key];
            const imageSize = imageSizes.imageSizes.find((size) => size.slug === key);
            if (imageSize) {
                options.push({
                    label: imageSize.name,
                    value: size.source_url,
                });
            }
        }
        return options;
    }

    return (
        <>
            {url && !isBlobURL(url) && (
                <InspectorControls>
                    <PanelBody title="Image Settings">
                        {id && (
                            <SelectControl
                                label="Image size"
                                options={getImageSizes()}
                                onChange={(value) => console.log(value)}
                            />
                        )}
                    </PanelBody>
                </InspectorControls>
            )}
            <div {...blockProps}>
                <div>
                    {url ? (
                        <>
                            <img src={url} alt={alt} />
                            {isBlobURL(url) && <Spinner />}
                        </>
                    ) : (
                        <MediaPlaceholder
                            icon="format-image"
                            onSelect={onSelectImage}
                            onError={onUploadError}
                            accept="image/*"
                            allowedTypes={["image"]}
                        />
                    )}

                </div>
            </div>
        </>
    );
}

export default Edit;

1 Answer 1

2

I am concerned the implementation is incorrect

If you just wanted to know whether you have correctly used useSelect, then yes, you have — and I would also return the same object as returned by your callback.

However, instead of const imageSizes = useSelect( ... ), I'd just do const { image, imageSizes } = useSelect( ... ), i.e. unpack the properties, and then I would not need the const { image } = imageSizes; and I also would just use imageSizes instead of imageSizes.imageSizes.

But that's just my personal preference, and one reason is because unpacking would make the code less.

1
  • 1
    Awesome, thanks Sally! Dec 13, 2021 at 12:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.