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

使用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 16:12:40