I'm creating a custom Gutenberg block. It works fine on save and appears on the front end, but as soon I come back to it it reads.
Block contains invalid or unexpected content
When I go in to resolve the block, I get an extra figure
inserted around my MediaUpload
component.
The console output shows the structure of block except with the text added in.
I saw a similar issue where the HTML nodes of edit function didn't match up with save function HTML nodes. After seeing that, I doubled check to make sure my nodes lined and I believe they do, unless I'm skipping over something. Here is the code for the block:
const { RichText, MediaUpload, PlainText } = wp.editor;
const { registerBlockType } = wp.blocks;
const { Button } = wp.components;
import './style.scss';
import './editor.scss';
registerBlockType('stackoverflow/image-card', {
title: "Image Card",
icon: 'feedback',
category: 'common',
attributes: {
title: {
source: 'text',
selector: '.imageCard__title'
},
body: {
type: 'string',
source: 'children',
selector: '.imageCard__body'
},
imageAlt: {
attribute: 'alt',
selector: '.imageCard__image'
},
imageUrl: {
attribute: 'src',
selector: '.imageCard__image'
}
},
edit({ attributes, className, setAttributes }) {
const getImageButton = (openEvent) => {
if(attributes.imageUrl) {
return (
<img
src={ attributes.imageUrl }
onClick={ openEvent }
className="image"
/>
);
}
else {
return (
<div className="button-container">
<Button
onClick={ openEvent }
className="button button-large"
>
Pick an image
</Button>
</div>
);
}
};
return (
<div className="container">
<MediaUpload
onSelect={ media => { setAttributes({ imageAlt: media.alt, imageUrl: media.url }); } }
type="image"
value={ attributes.imageID }
render={ ({ open }) => getImageButton(open) }
/>
<h3>
<PlainText
onChange={ content => setAttributes({ title: content }) }
value={ attributes.title }
placeholder="Your card title"
className="heading"
/>
</h3>
<div className={className}>
<RichText
onChange={ content => setAttributes({ body: content }) }
value={ attributes.body }
multiline="p"
placeholder="Your card text"
/>
</div>
</div>
);
},
save({ attributes }) {
const cardImage = (src, alt) => {
if(!src) return null;
if(alt) {
return (
<img
className="card__image"
src={ src }
alt={ alt }
/>
);
}
// No alt set, so let's hide it from screen readers
return (
<img
className="card__image"
src={ src }
alt=""
aria-hidden="true"
/>
);
};
return (
<div className="container">
<img
className="card__image"
src={ attributes.imageUrl }
alt={ attributes.imageAlt }
/>
<h3 className="card__title">{ attributes.title }</h3>
<div className="card__body">
{ attributes.body }
</div>
</div>
);
}
});