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) }) }
问题原因
splice方法返回值误用:splice会直接修改原数组,返回的是被删除的元素组成的数组,而非修改后的完整数组。将其赋值给panels时,只会保留被替换的单个面板,其余面板全部丢失。- 直接修改原属性:直接修改
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
相关产品推荐
相关产品推荐

