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

React拖拽功能报错:Cannot read properties of undefined reading 'indexOf'求助

问题排查与修复

核心错误原因

  1. 笔误导致属性未找到:drop函数里的currentBoard.item.indexOf(currentItem)是拼写错误,应该是currentBoard.items(复数形式),少了s导致访问undefined的indexOf方法,触发报错。
  2. 直接修改State对象:使用splice直接修改currentBoard.items和board.items,违反React状态不可变原则,会导致状态更新异常。
  3. 未处理初始空状态:currentBoard初始值为null,若在未拖拽时触发drop,访问currentBoard.items会报错。
  4. 缺少key属性:组件循环渲染时未添加唯一key,会触发keys相关警告。

修复后的完整代码

import { useState } from 'react';

const App = () => {
    const [boards, setBoards] = useState([
        {id: 1, title: "Не начато", items: [{id: 1, title:"a"}, {id:2, title:"b"}, {id:3, title:"c"}] }
    ])

    const [currentBoard, setCurrentBoard] = useState(null)
    const [currentItem, setCurrentItem] = useState(null)

    function dOH (e){ e.preventDefault() }
    function dLH (e){}
    function dSH (e, board, item){
        setCurrentBoard(board)
        setCurrentItem(item)
    }
    function dEH (e){}


    function drop(e, targetBoard, targetItem) {
        e.preventDefault()
        // 避免未拖拽时触发drop导致的空值错误
        if (!currentBoard || !currentItem) return;

        // 创建原数组副本,避免直接修改state
        const sourceItems = [...currentBoard.items];
        const currentIndex = sourceItems.indexOf(currentItem);
        if (currentIndex === -1) return; // 未找到元素时直接返回
        sourceItems.splice(currentIndex, 1);

        const targetItems = [...targetBoard.items];
        const dropIndex = targetItems.indexOf(targetItem);
        targetItems.splice(dropIndex + 1, 0, currentItem);

        // 更新boards状态,创建新对象避免直接修改原state
        setBoards(prevBoards => prevBoards.map(b => {
            if(b.id === targetBoard.id){
                return {...b, items: targetItems};
            }
            if(b.id === currentBoard.id){
                return {...b, items: sourceItems};
            }
            return b;
        }))

        // 重置当前拖拽状态
        setCurrentBoard(null);
        setCurrentItem(null);
    }

    return (
        <div>
            {boards.map (board =>
                <div key={board.id}>
                    <div>{board.title}</div>
                    {board.items.map (item =>
                        <div 
                            key={item.id}
                            onDragOver={(e) => dOH(e)}
                            onDragLeave={(e) => dLH(e)}
                            onDragStart={(e) => dSH(e, board, item)}
                            onDragEnd={(e) => dEH(e)}
                            onDrop={(e) => drop(e, board, item)}
                            draggable={true}
                        >
                            {item.title} 
                        </div>
                    )}
                </div>
            )}
        </div>
    )
}

export default App

关键修改说明

  • 修正了currentBoard.item的拼写错误,改为currentBoard.items。
  • 对数组使用扩展运算符[...arr]创建副本,再进行splice操作,遵循状态不可变原则。
  • 在drop函数开头添加空值判断,避免未拖拽时的报错。
  • 给map循环的元素添加了key属性,使用board.id和item.id作为唯一标识。
  • 更新boards时使用函数式更新prevBoards,确保获取最新的状态值。
  • 拖拽完成后重置currentBoard和currentItem,避免重复触发异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 00:12:04