使用react-beautiful-dnd拖拽或重排任务卡片后浏览器页面空白问题求助
我帮你梳理了代码里的几个核心问题,这应该就是导致拖拽后页面空白、StrictMode下拖拽失效的根源:
1. Droppable ID 完全不匹配
你在Tasks.jsx里给两个Droppable组件设置的droppableId是"tasket"和"tasketer",但在handleOnDragEnd的逻辑里,判断容器用的却是"weeklyTasks"和"dailyTasks"。这种不匹配会让react-beautiful-dnd在拖拽结束时找不到对应的目标容器,直接抛出错误导致页面崩溃。
修复方法:把两个Droppable的droppableId改成和逻辑判断一致的值:
// 第一个Droppable(Weekly Tasks) <Droppable droppableId="weeklyTasks"> {(provided) => { return ( <div className="weekly-box" {...provided.droppableProps} ref={provided.innerRef}> <h3>Weekly Tasks</h3> {/* 任务列表代码 */} </div> ) }} </Droppable> // 第二个Droppable(Daily Targets) <Droppable droppableId="dailyTasks"> {(provided) => { return ( <div className="daily-box" {...provided.droppableProps} ref={provided.innerRef}> <h3>Daily Targets</h3> {/* 任务列表代码 */} </div> ) }} </Droppable>
2. 直接修改原状态数组,违反React不可变原则
在跨容器拖拽的逻辑中,你直接将状态数组赋值给临时变量(比如let tempWeeklyTasks = weeklyTasks;),这其实是引用了原状态的内存地址,修改临时变量会直接篡改原状态。这种操作会导致React无法正确追踪状态变化,在StrictMode下重复渲染的机制会进一步放大这个问题,直接导致拖拽功能完全失效。
修复方法:每次操作前都创建数组的浅拷贝,比如用扩展运算符或者Array.from():
const handleOnDragEnd = result => { const { source, destination } = result if (!destination) return; if (source.droppableId === destination.droppableId) { // 同容器拖拽的逻辑保持不变(这里已经用了Array.from,是对的) if (source.droppableId === "weeklyTasks") { let tempWeeklyTasks = Array.from(weeklyTasks) const [reorderedItem] = tempWeeklyTasks.splice(source.index, 1); tempWeeklyTasks.splice(destination.index, 0, reorderedItem); setWeeklyTasks(tempWeeklyTasks) } else { let tempDailyTasks = Array.from(dailyTasks) const [reorderedItem] = tempDailyTasks.splice(source.index, 1); tempDailyTasks.splice(destination.index, 0, reorderedItem); setDailyTasks(tempDailyTasks) } } else { // 跨容器拖拽:创建数组拷贝,避免修改原状态 let tempWeeklyTasks = [...weeklyTasks]; let tempDailyTasks = [...dailyTasks]; if (source.droppableId === "weeklyTasks") { const [removed] = tempWeeklyTasks.splice(source.index, 1) tempDailyTasks.splice(destination.index, 0, removed) setWeeklyTasks(tempWeeklyTasks) setDailyTasks(tempDailyTasks) } else { const [removed] = tempDailyTasks.splice(source.index, 1); tempWeeklyTasks.splice(destination.index, 0, removed); setWeeklyTasks(tempWeeklyTasks); setDailyTasks(tempDailyTasks); } } }
3. 不必要的useEffect导致状态强制重置
你在Tasks组件里加了一段useEffect,会在tasks变化时把weeklyTasks重置为初始的静态数据。但tasks是导入的静态常量,永远不会变化,这个useEffect会在组件每次渲染(包括拖拽后状态更新)时都执行,把你调整好的任务列表又变回初始值。在StrictMode下,这个useEffect会执行两次,让问题更明显。
修复方法:直接删掉这段多余的useEffect:
// 删掉以下代码 // useEffect(() => { // setWeeklyTasks(tasks) // }, [tasks]);
做完这些修改后,无论是关闭StrictMode还是开启它,拖拽功能都应该能正常工作,不会再出现页面空白的问题。
内容的提问来源于stack exchange,提问作者scisamir

