React拖拽组件报错:无法找到ID为droppable-list的可放置项
解决React-beautiful-dnd报错:Invariant failed: Cannot find droppable entry with id [droppable-list]
这个报错源于react-beautiful-dnd内部状态与组件实际渲染状态不匹配,结合你提供的代码,给出以下针对性修复方案:
1. 替换索引为唯一标识作为Draggable的key和draggableId
你当前用index作为Draggable的key和draggableId组成部分,拖拽会改变元素索引,导致react-beautiful-dnd无法正确跟踪可拖拽项身份,进而引发Droppable匹配失败。
修改代码:
{dataEXEditar?.map((element, index) => ( // 用元素自身唯一ID替换索引作为key和draggableId <Draggable key={element.id} draggableId={`draggable-item-${element.id}`} index={index}> {/* 其余代码保持不变 */} </Draggable> ))}
如果数据没有自带唯一ID,可在获取数据时为每个元素生成(比如通过uuid库)。
2. 确保Droppable在数据加载前后始终挂载
当dataEXEditar为undefined或空数组时,即便Droppable仍渲染,react-beautiful-dnd也可能无法正确注册它。可添加空状态占位,避免Droppable内部无内容:
<DragDropContext onDragEnd={handleDragEnd}> <List sx={{ overflowY: "auto", maxHeight: "20vh" }}> <Droppable droppableId="droppable-list"> {(provided) => ( <div ref={provided.innerRef} {...provided.droppableProps}> {dataEXEditar?.length ? ( dataEXEditar.map((element, index) => ( <Draggable key={element.id} draggableId={`draggable-item-${element.id}`} index={index}> {/* 其余代码不变 */} </Draggable> )) ) : ( <ListItem> <ListItemText primary="暂无数据" /> </ListItem> )} {provided.placeholder} </div> )} </Droppable> </List> </DragDropContext>
3. 调整Droppable与Material-UI List的嵌套关系
Material-UI的List会生成额外DOM结构,可能导致provided.innerRef未正确绑定到Droppable容器。可将List放入Droppable内部,让ref直接绑定到List:
<DragDropContext onDragEnd={handleDragEnd}> <Droppable droppableId="droppable-list"> {(provided) => ( <List ref={provided.innerRef} {...provided.droppableProps} sx={{ overflowY: "auto", maxHeight: "20vh" }} > {dataEXEditar?.map((element, index) => ( <Draggable key={element.id} draggableId={`draggable-item-${element.id}`} index={index}> {/* 其余代码不变 */} </Draggable> ))} {provided.placeholder} </List> )} </Droppable> </DragDropContext>
4. 确保拖拽结束后状态同步正确
handleDragEnd中更新数据顺序时,要保证状态正确同步,避免内部上下文混乱:
const handleDragEnd = (result) => { if (!result.destination) return; // 重新排序数据 const items = Array.from(dataEXEditar); const [reorderedItem] = items.splice(result.source.index, 1); items.splice(result.destination.index, 0, reorderedItem); // 正确更新状态 setDataEXEditar(items); };
以上方案可单独或组合使用,解决“刷新后有时能正常工作”的不稳定问题。
内容的提问来源于stack exchange,提问作者Leandro Sampaio
相关产品推荐
相关产品推荐

