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

React DnD索引变更后拖拽失效问题求助

React DnD拖拽排序异常:元素索引变更后无法再次拖拽

我尝试用React DnD实现数组moduleList中元素的排序功能,但出现异常:元素仅能被拖拽到索引发生变更一次,之后便无法再响应拖拽操作。具体表现:

  • 将索引0的元素拖拽到索引1和2之间,前两个元素成功交换位置及索引,但之后这两个元素不再响应拖拽;
  • 索引2的元素可继续拖拽,但放置到新位置后也会失效;
  • 若将索引0的元素直接拖拽到最后位置,所有元素索引变更后均无法拖拽。

相关简化代码如下:

const App = ({ modules, status }) => {
    const [moduleList, setModuleList] = useState(modules);

    const dropModule = (input) => {
        const { index, module } = input;
        if (index === null) return;
        let newModules = [...moduleList]
        if (module.key) {
            let toDeleteIndex = moduleList.findIndex(mod => {
                return mod.key === module.key;
            })
            if (toDeleteIndex < 0) return;
            newModules.splice(toDeleteIndex, 1);
            newModules.splice(index, 0, module)
        } else {
            newModules.splice(index, 0, { type: "standard_module", key: Math.random() })
        }
        console.log({newModules})
        setModuleList(newModules)
    }

    const renderModule = (module, index) => {
        const dropRef = useRef(null);
        const dragRef = useRef(null);

        const [{ isOver }, drop] = useDrop({
            accept: "MODULE",
            drop: () => ({module, index}),
            collect: monitor => ({
                isOver: !!monitor.isOver()
            })
        })

        const [{ isDragging }, drag, dragPreview] = useDrag({
            type: "MODULE",
            item: module,
            end(item, monitor) {
                const dropResult = monitor.getDropResult()
                if (dropResult) dropModule({ module: item, index: dropResult?.index });
            },
            collect: monitor => ({
                isDragging: !!monitor.isDragging(),
            })
        })

        dragPreview(drop(dropRef))
        drag(dragRef)

        return (
            <div ref={dropRef} key={`${index}-${module.key}`}>
                <div ref={dragRef} className="module-menu"><i>expand</i>{index}</div>
                ...module element (code not relevant, I don't think)
            </div>
        )
    }
    
    return (
        <article>
            {
                moduleList.map((module, x) => {
                    return renderModule(module, x)
                })
            }
        </article>
    )

}

我认为代码逻辑和其他示例一致,但找不到问题根源。另外,给module添加key属性是为了解决React无法识别元素位置交换的问题——之前用索引作为key时,React只会在数组末尾渲染新元素,唯一key能让React识别元素位置变更,不确定这是否与当前问题有关。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 10:35:24