You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WordPress自定义区块:动态更新Block Templates数据不渲染问题排查

问题

开发WordPress自定义区块时,尝试在首次useEffect调用后用获取到的属性数据动态更新Block Templates。首次渲染时属性为空,显示默认值;跟踪代码发现模板已更新,但调用useInnerBlocksProps传入修订后的模板后,数据仍未渲染到界面。已确认最后一次渲染的模板定义正确,但界面显示不符,请问遗漏了什么?

export default function Edit(props) {
const { PanelBody, PanelRow } = wp.components;
const { attributes, setAttributes } = props;

useEffect(() => {

    setAttributes({'name': 'Edward Alan Thompson'});
    setAttributes({'birth_date': '1 jan 1900'});
    setAttributes({'death_date': '31 Dec 1990'});
    setAttributes({'imageUrl': 'http://wordpressdevel.local/wp-content/uploads/2022/07/1.png'});
}, []);

const blockProps = useBlockProps( {
    style:{minHeight: 40, width: '100%', border: "1px dotted red"}
});

const innerBlocksProps = useInnerBlocksProps(
    {orientation: "horizontal"},
    {template: [
            [ 'core/columns', { columns: 2 }, [
                [ 'core/column', {width: "20%"}, [
                    [ 'core/image', { url: attributes.imageUrl??''} ]
                ] ],
                [ 'core/column', {}, [
                    [ 'core/heading', { content: attributes.name??''} ],
                    [ 'core/paragraph', { content: 'b. ' + attributes.birth_date??''} ],
                    [ 'core/paragraph', { content: 'd. ' + attributes.death_date??''} ]
                ] ],
            ]
            ]
        ]}
);

return (
    <div >
        <InspectorControls>
            <PanelBody title="General" initialOpen={true}>
                <PanelRow>
                </PanelRow>
            </PanelBody>
        </InspectorControls>
        <div {...blockProps}>
            <div {...innerBlocksProps}></div></div>
    </div>
);
}
解决方案

核心问题是:useInnerBlocksProps的模板仅在区块首次初始化时生效一次,后续属性更新不会自动重新应用模板。要实现动态更新,需要手动同步内部区块内容:

  • 步骤1:引入必要的工具函数
    用到wp.data的select和dispatch来操作内部区块,以及wp.blocks的模板解析方法。

  • 步骤2:监听属性变化,手动更新内部区块
    在属性更新时,重新构建模板并替换内部区块内容。修改后的完整代码如下:

import { useEffect } from '@wordpress/element';
import { useSelect, useDispatch } from '@wordpress/data';
import { useBlockProps, useInnerBlocksProps, InspectorControls } from '@wordpress/block-editor';

export default function Edit(props) {
    const { PanelBody, PanelRow } = wp.components;
    const { attributes, setAttributes, clientId } = props;
    const { getBlocks } = useSelect('core/block-editor');
    const { replaceInnerBlocks } = useDispatch('core/block-editor');

    // 首次初始化属性
    useEffect(() => {
        setAttributes({
            name: 'Edward Alan Thompson',
            birth_date: '1 jan 1900',
            death_date: '31 Dec 1990',
            imageUrl: 'http://wordpressdevel.local/wp-content/uploads/2022/07/1.png'
        });
    }, []);

    // 属性更新时同步内部区块
    useEffect(() => {
        // 确保属性都已加载完成
        if (!attributes.name || !attributes.imageUrl) return;

        // 构建最新的内部区块模板
        const newTemplate = [
            [ 'core/columns', { columns: 2 }, [
                [ 'core/column', {width: "20%"}, [
                    [ 'core/image', { url: attributes.imageUrl } ]
                ] ],
                [ 'core/column', {}, [
                    [ 'core/heading', { content: attributes.name } ],
                    [ 'core/paragraph', { content: `b. ${attributes.birth_date}` } ],
                    [ 'core/paragraph', { content: `d. ${attributes.death_date}` } ]
                ] ],
            ] ]
        ];

        // 将模板转换为区块编辑器可识别的对象格式
        const parsedBlocks = wp.blocks.parseBlocksFromTemplate(newTemplate);
        // 替换当前区块的内部内容
        replaceInnerBlocks(clientId, parsedBlocks, false);
    }, [attributes.name, attributes.birth_date, attributes.death_date, attributes.imageUrl, clientId, replaceInnerBlocks]);

    const blockProps = useBlockProps( {
        style:{minHeight: 40, width: '100%', border: "1px dotted red"}
    });

    // 保留初始化模板,后续更新由useEffect处理
    const innerBlocksProps = useInnerBlocksProps(
        {orientation: "horizontal"},
        {
            template: [
                [ 'core/columns', { columns: 2 }, [
                    [ 'core/column', {width: "20%"}, [
                        [ 'core/image', { url: ''} ]
                    ] ],
                    [ 'core/column', {}, [
                        [ 'core/heading', { content: ''} ],
                        [ 'core/paragraph', { content: ''} ],
                        [ 'core/paragraph', { content: ''} ]
                    ] ],
                ] ]
            ],
            templateLock: 'all' // 可选:锁定模板防止用户手动修改
        }
    );

    return (
        <div >
            <InspectorControls>
                <PanelBody title="General" initialOpen={true}>
                    <PanelRow>
                    </PanelRow>
                </PanelBody>
            </InspectorControls>
            <div {...blockProps}>
                <div {...innerBlocksProps}></div>
            </div>
        </div>
    );
}
  • 关键注意点
    1. template仅负责区块首次渲染的初始结构,后续动态更新必须通过replaceInnerBlocks手动触发;
    2. 监听属性的useEffect要把所有需要触发更新的属性加入依赖数组,确保属性变化时执行同步逻辑;
    3. clientId是当前区块的唯一标识,用来定位要更新的内部区块容器;
    4. wp.blocks.parseBlocksFromTemplate是将模板数组转换为区块对象的必要步骤,不能省略。

内容的提问来源于stack exchange,提问作者ed4becky

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 17:05:21