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

WordPress Gutenberg块更新属性时其他面板消失求助

WordPress Gutenberg块面板更新时其他面板消失问题修复

问题概述

开发WordPress Gutenberg块时,块属性包含panels对象数组。当存在2个及以上面板时,在任意面板输入内容(如h2标题),其他所有面板会直接消失。

块属性定义

attributes: {
    panels: {
        type: "array",
        default: [{
            id: uuid(),
            h2: "",
            h3: "",
            backgroundImage: "",
            highlightText: "",
            featureList: [""],
            buttonText: "",
            buttonUrl: "",
            buttonColor: ""
        }]
    }
}

编辑器JSX代码

return (
    <div {...blockProps}>
        <h2 className="tpp-heading">Tariff Product Panel</h2>
        {props.attributes.panels.map((panel, panelIndex) => {
            return (
                <div className="tpp-product" id={panel.id}>
                    <h2 className="tpp-sub-heading">Product {panelIndex + 1}</h2>
                    <Button
                        onClick={() => removePanel(panelIndex)}
                        className="tpp-remove-panel"
                        title="Delete Panel">
                        <Icon
                            icon="remove"
                        />
                    </Button>
                    <Flex>
                        <FlexBlock className="tpp-attribute">
                            <TextControl
                                value={panel.h2}
                                label="Heading"
                                onChange={(value) => updateAttribute(panelIndex, value, "h2", panel.id)}
                            />
                        </FlexBlock>
                        <FlexBlock>
                            <TextControl
                                value={panel.h3}
                                label="Sub Heading"
                                onChange={(value) => updateAttribute(panelIndex, value, "h3", panel.id)}
                            />
                        </FlexBlock>
                    </Flex>
                    <Flex>
                        <FlexBlock className="tpp-attribute">
                            <TextControl
                                value={panel.backgroundImage}
                                label="Background Image"
                                onChange={(value) => updateAttribute(panelIndex, value, "backgroundImage", panel.id)}
                            />
                        </FlexBlock>
                        <FlexBlock>
                            <TextControl
                                value={panel.highlightText}
                                label="Highlight Text (if filled in, panel will have highlight)"
                                onChange={(value) => updateAttribute(panelIndex, value, "highlightText", panel.id)}
                            />
                        </FlexBlock>
                    </Flex>
                    <Flex>
                        <FlexBlock className="tpp-attribute">
                            <TextControl
                                value={panel.buttonText}
                                label="Button Text"
                                onChange={(value) => updateAttribute(panelIndex, value, "buttonText", panel.id)}
                            />
                        </FlexBlock>
                        <FlexBlock>
                            <SelectControl
                                label="Button Color"
                                value={panel.buttonColor}
                                options={[
                                    { label: 'Default', value: 'default' },
                                    { label: 'Primary', value: 'primary' },
                                    { label: 'Secondary', value: 'secondary' },
                                ]}
                                onChange={(value) => updateAttribute(panelIndex, value, "buttonColor", panel.id)}
                            />
                        </FlexBlock>
                    </Flex>
                    <Flex>
                        <FlexBlock className="tpp-attribute">
                            <TextControl
                                value={panel.buttonUrl}
                                label="Button URL"
                                onChange={(value) => updateAttribute(panelIndex, value, "buttonUrl", panel.id)}
                            />
                        </FlexBlock>
                    </Flex>
                    <label class="components-base-control__label css-1v57ksj">Features:</label>
                    {panel.featureList.map((feature, featureIndex) => {
                        return (
                            <Flex>
                                <FlexBlock>
                                    <TextControl
                                        value={feature}
                                        onChange={(feature) => updateFeaturelist(panelIndex, featureIndex, feature)}
                                    />
                                </FlexBlock>
                                <FlexBlock>
                                    <Button
                                        onClick={() => removeFeature(panelIndex, featureIndex)}
                                        className="tpp-delete-feature"
                                        title="Delete Feature">
                                        <Icon
                                            icon="trash"
                                        />
                                    </Button>
                                </FlexBlock>
                            </Flex>
                        )
                    })}
                    <Button
                        onClick={() => addNewFeature(panelIndex)}
                        className="tpp-add-feature">
                        Add feature
                    </Button>
                </div>
            )
        })}
        <Button
            isPrimary
            onClick={() => addNewProduct()}>
            Add product
        </Button>
    </div>
)

原更新函数(问题所在)

function updateAttribute(panelIndex, value, el, id) {
    let panel = props.attributes.panels.find((item) => item.id == id)
    panel[el] = value
    props.setAttributes({
        panels: props.attributes.panels.splice(panelIndex, 1, panel)
    })
}

问题原因

  1. splice方法返回值误用:splice会直接修改原数组,返回的是被删除的元素组成的数组,而非修改后的完整数组。将其赋值给panels时,只会保留被替换的单个面板,其余面板全部丢失。
  2. 直接修改原属性:直接修改props.attributes中的数组和对象,不符合Gutenberg状态更新的不可变性要求,可能导致状态检测失效。

修复后的更新函数

function updateAttribute(panelIndex, value, el) {
    // 创建原数组的浅拷贝,避免直接修改原属性
    const updatedPanels = [...props.attributes.panels];
    // 创建目标面板的新对象,更新指定属性,保证不可变性
    updatedPanels[panelIndex] = {
        ...updatedPanels[panelIndex],
        [el]: value
    };
    // 设置新的属性数组
    props.setAttributes({ panels: updatedPanels });
}

配套修改

调用updateAttribute时无需再传入panel.id参数,修改所有TextControl和SelectControl的onChange回调:

// 示例:Heading的回调修改
onChange={(value) => updateAttribute(panelIndex, value, "h2")}

修复说明

  • 使用扩展运算符...创建数组和对象的副本,保证状态更新的不可变性,符合React/Gutenberg最佳实践
  • 通过panelIndex直接定位目标面板,无需额外通过id查找,逻辑更高效清晰
  • 避免直接修改原属性对象,确保Gutenberg能正确检测到状态变化并重新渲染

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 02:50:30