admin管理员组文章数量:1402122
I am attempting to refactor a block plugin that provides a custom embed from a third-party platform. I would like the generated embed to re-render in the editor when the user changes attributes. I had this working fine a few years ago, before the editor was an iframe. I am having some difficulty achieving the same result now.
My edit function looks like this:
export default function Edit({ attributes, setAttributes }) {
const blockProps = useBlockProps({
className: 'altmetric-embed'
});
const onChangeIdentifier = (value) => {
setAttributes({ identifier: value });
};
useEffect(() => {
_altmetric_embed_init( );
}, [attributes.identifier]);
return (
<>
<InspectorControls>
<PanelBody title={__('Identifier')} >
<PanelRow>
<TextControl
label='DOI'
value={attributes.identifier}
onChange={onChangeIdentifier}
/>
</PanelRow>
</PanelBody>
</InspectorControls>
<div
{ ...blockProps}
data-doi={attributes.identifier}
></>
</>
);
}
The _altmetric_embed_init
function is provided by the third-party in the instance when you want to refresh the embed after the DOM is loaded. (Information on that is here: .html#technical-information.) I've registered their script in PHP in the standard way:
wp_register_script(
'altmetrics-official-embed',
'.js',
'',
'',
true
);
And enqueued it via the block.json
file:
{
"$schema": ".json",
"apiVersion": 3,
"example": {},
"supports": {
"html": false
},
"attributes": {
"identifier": {
"type": "string"
},
"editorScript": "file:./index.js",
"editorStyle": "file:./editor.css",
"style": "file:./style.css",
"script": "altmetrics-official-embed"
}
As far as I can tell the script is enqueued correctly and useEffect
is firing correctly, but the embed doesn't re-render. I assume the iframe is tripping this up somewhere? I believe they are using defaultView
correctly (/), but their code is of course minimized. Should I be using useRefEffect
here? Any pointers on the best way to do that?
I am attempting to refactor a block plugin that provides a custom embed from a third-party platform. I would like the generated embed to re-render in the editor when the user changes attributes. I had this working fine a few years ago, before the editor was an iframe. I am having some difficulty achieving the same result now.
My edit function looks like this:
export default function Edit({ attributes, setAttributes }) {
const blockProps = useBlockProps({
className: 'altmetric-embed'
});
const onChangeIdentifier = (value) => {
setAttributes({ identifier: value });
};
useEffect(() => {
_altmetric_embed_init( );
}, [attributes.identifier]);
return (
<>
<InspectorControls>
<PanelBody title={__('Identifier')} >
<PanelRow>
<TextControl
label='DOI'
value={attributes.identifier}
onChange={onChangeIdentifier}
/>
</PanelRow>
</PanelBody>
</InspectorControls>
<div
{ ...blockProps}
data-doi={attributes.identifier}
></>
</>
);
}
The _altmetric_embed_init
function is provided by the third-party in the instance when you want to refresh the embed after the DOM is loaded. (Information on that is here: https://badge-docs.altmetric/getting-started.html#technical-information.) I've registered their script in PHP in the standard way:
wp_register_script(
'altmetrics-official-embed',
'https://d1bxh8uas1mnw7.cloudfront/assets/embed.js',
'',
'',
true
);
And enqueued it via the block.json
file:
{
"$schema": "https://schemas.wp/trunk/block.json",
"apiVersion": 3,
"example": {},
"supports": {
"html": false
},
"attributes": {
"identifier": {
"type": "string"
},
"editorScript": "file:./index.js",
"editorStyle": "file:./editor.css",
"style": "file:./style.css",
"script": "altmetrics-official-embed"
}
As far as I can tell the script is enqueued correctly and useEffect
is firing correctly, but the embed doesn't re-render. I assume the iframe is tripping this up somewhere? I believe they are using defaultView
correctly (https://make.wordpress/core/2021/06/29/blocks-in-an-iframed-template-editor/), but their code is of course minimized. Should I be using useRefEffect
here? Any pointers on the best way to do that?
2 Answers
Reset to default 0I would like the generated embed to re-render in the editor when the user changes attributes.
You can do that by creating a ref using useRef
and then passing the ref to _altmetric_embed_init
, like so:
const ref = useRef();
useEffect(() => {
_altmetric_embed_init(ref.current);
}, [attributes.identifier]);
You don't have to use useRefEffect
and you also don't need to load altmetrics-official-embed
in the editor canvas (which is an iframe
).
- In my
block.json
file, I used"editorScript": [ "file:./index.js", "altmetrics-official-embed" ]
and removed thescript
entry.
However, instead of assigning the altmetric-embed
class and data-doi
attribute to your block wrapper, you should assign them to an element in that wrapper, like so:
<div {...useBlockProps({ ref })}>
<div
className="altmetric-embed"
data-doi={attributes.identifier}
>
</div>
</div>
Use useRef
to get a reference to the container and call _altmetric_embed_init()
on the DOM node or its context.
import { useBlockProps, InspectorControls } from '@wordpress/block-editor';
import { PanelBody, PanelRow, TextControl } from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import { useEffect, useRef } from '@wordpress/element';
export default function Edit({ attributes, setAttributes }) {
const blockProps = useBlockProps({
className: 'altmetric-embed',
});
const { identifier } = attributes;
const embedRef = useRef();
const onChangeIdentifier = (value) => {
setAttributes({ identifier: value });
};
useEffect(() => {
// Make sure the script is available and the embed container is mounted
if (typeof _altmetric_embed_init === 'function' && embedRef.current) {
_altmetric_embed_init();
}
}, [identifier]);
return (
<>
<InspectorControls>
<PanelBody title={__('Identifier')}>
<PanelRow>
<TextControl
label="DOI"
value={identifier}
onChange={onChangeIdentifier}
/>
</PanelRow>
</PanelBody>
</InspectorControls>
<div
{...blockProps}
data-doi={identifier}
ref={embedRef}
></div>
</>
);
}
本文标签: Rerendering a custom embed block on attribute change
版权声明:本文标题:Re-rendering a custom embed block on attribute change 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744344004a2601648.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
script
is for the frontend,editorScript
is for the backend. Also keep in mind that thediv
with the block props might have the classname the script is looking for but it's not a HTML tag, it's a react component. The DOM element the script finds and attaches to may be destroyed and recreated at any moment and altmetrics might not be able to handle that. It might be easier to use the second method on the altmetrics docs anduseRef
but that's moving outside the realm of WordPress and into general react programming – Tom J Nowell ♦ Commented Mar 18 at 18:38script
enqueues for both front-end and editor: developer.wordpress/block-editor/reference-guides/block-api/… – jshwlkr Commented Mar 18 at 18:47