ReactSortable嵌套组件问题:拖拽元素无法保存至布局块
跨列表拖拽嵌套元素问题修复方案
问题根源
布局块无法保存内部拖拽元素,本质是嵌套元素的状态更新与渲染逻辑未实现:拖拽段落进入layout2的嵌套块时,没有正确定位父布局元素并更新其子元素集合,同时嵌套块也没有渲染内部的子元素。
具体修复步骤
1. 补全元素数据结构
给layout2类型的元素添加children字段,用于存储内部嵌套的元素:
interface Layout2Element { id: string; type: 'layout2'; children: Element[]; } type Element = Layout2Element | ParagraphElement;
2. 修正拖拽事件处理
在onDrop函数中区分普通拖拽和嵌套块拖拽,针对嵌套块的情况,更新对应layout2元素的children:
const onDrop = (e: React.DragEvent, targetId: string, isNested = false) => { e.preventDefault(); const draggedId = e.dataTransfer.getData('text/plain'); const draggedElement = elements.find(el => el.id === draggedId); if (!draggedElement) return; if (isNested) { // 更新目标layout2的子元素列表 setEditorElements(prevElements => prevElements.map(el => { if (el.type === 'layout2' && el.id === targetId) { return { ...el, children: [...el.children, draggedElement] }; } return el; }) ); } else { // 原有拖拽到编辑器根节点的逻辑 setEditorElements(prev => [...prev, draggedElement]); } };
3. 修复嵌套块渲染逻辑
修改Layout2组件,遍历渲染自身的children元素:
const Layout2 = ({ id, children }: Layout2Element) => { return ( <div className="layout2"> {/* 第一个嵌套块 */} <div className="nested-block" onDragOver={(e) => e.preventDefault()} onDrop={(e) => onDrop(e, id, true)} > {children.map(child => child.type === 'paragraph' ? ( <Paragraph key={child.id} id={child.id} content={child.content} /> ) : null )} </div> {/* 第二个嵌套块 */} <div className="nested-block" onDragOver={(e) => e.preventDefault()} onDrop={(e) => onDrop(e, id, true)} > {children.map(child => child.type === 'paragraph' ? ( <Paragraph key={child.id} id={child.id} content={child.content} /> ) : null )} </div> </div> ); };
4. 初始化布局元素的children
在初始元素数组中给layout2设置空的children数组:
const elements: Element[] = [ { id: 'layout-1', type: 'layout2', children: [] }, { id: 'para-1', type: 'paragraph', content: '示例段落1' }, { id: 'para-2', type: 'paragraph', content: '示例段落2' }, ];
效果验证
- 将layout2拖拽到编辑器,可见两个空的嵌套块;
- 将段落拖拽到任意嵌套块,段落会立即显示在块内,且编辑器的状态会正确保存嵌套元素。
内容的提问来源于stack exchange,提问作者Maxim Gordiyenko
相关产品推荐
相关产品推荐

