I’m building a custom Gutenberg block that displays a gallery of images. Each image has a custom attachment meta field called _oembed_url, which stores an external video URL (for example, YouTube or Vimeo). This field is added via the Attachment_fields_to_edit and Attachment_fields_to_save filters in PHP.
Since the onSelect callback from MediaUpload or MediaPlaceholder does not contain attachment meta fields, I use wp.data.select(‘core’).getEntityRecord(‘postType’, ‘attachment’, image.id) to retrieve the missing meta value and include it in the images attribute of my block.
Here is the relevant part of my code:
<>
<InspectorControls>
<PanelBody title={__('Settings', 'my-domain' )}>
</PanelBody>
</InspectorControls>
{images.length > 0 && (
<BlockControls>
<ToolbarGroup>
<MediaUploadCheck>
<MediaUpload
allowedTypes={['image']}
multiple={true}
gallery={true}
value={images.map((image) => image.id)}
onSelect={setImages}
render={({ open }) => (
<ToolbarButton onClick={open}>
{__('Edit images', 'my-domain')}
</ToolbarButton>)}
/>
</MediaUploadCheck>
</ToolbarGroup>
</BlockControls>
)}
<MediaUploadCheck>
{images.length > 0 ?
<figure {...blockProps}>
<div className="gallery-thumbnails">
{
displayImages(images)
}
</div>
</figure>
:
<div {...blockProps}>
<MediaPlaceholder
accept="image/*"
allowedTypes={['image']}
onSelect={setImages}
multiple={true}
gallery={true}
addToGallery={true}
handleUpload={true}
labels={ { title: __('Project Gallery', 'my-domain'
) } }
/>
</div>
}
</MediaUploadCheck>
</>
The setImages() code:
const setImages = (value) => {
const imageDetails = value.map(image => {
const oembed = wp.data.select('core')
.getEntityRecord('postType', 'attachment', image.id)
?.meta?._oembed_url || '';
return {
id: image.id,
url: image.url,
alt: image.alt,
caption: image.caption,
oembed,
};
});
setAttributes({ images: imageDetails });
};
And I render the gallery like this:
const displayImages = (images) => (
images.map((image, index) => {
const hasOembed = image.oembed && image.oembed.trim() !== '';
return (
<div className={`gallery-thumbnail ${hasOembed ? 'has-oembed' : ''}`} key={index}>
<figure>
<img src={image.url} alt={image.alt} />
</figure>
</div>
);
})
);
The problem is that getEntityRecord() is asynchronous: when onSelect is executed, sometimes the _oembed_url metafield is not yet available. As a result, some image.oembed values ​​are empty even though they exist. Once the data is finally loaded, the component isn’t automatically re-rendered to show the updated meta (and the has-oembed CSS class is never added to the div).
Question: How can I make my block wait for the metafields to become available before setting the images attribute or automatically update the component once getEntityRecord() has finished loading?
#correctly #retrieve #attachment #metafields #WordPress #block #MediaUpload

