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

使用useState更新状态时对象初始数据被重置,关联react-beautiful-dnd拖拽组件

问题根因
  • 异步状态更新捕获旧值:你在axios请求回调中调用setInitialData时,使用的是作用域闭包缓存的初始initialData值,两次请求的回调拿到的都是同一个初始空值的initialData,后执行的set操作会覆盖前一次的更新结果,导致其中一列数据被重置。
  • Promise链写法不规范:你在then中直接执行console.log和第二个axios请求,没有正确返回Promise,导致异步执行顺序不可控;同时useEffect的回调函数不能直接标记为async,会导致返回Promise而非清理函数,触发React警告。
  • 冗余状态依赖:你同时维护了initialData和columns两个高度相似的状态,监听initialData更新columns的逻辑中也捕获了旧的columns值,可能引发额外的状态覆盖问题。
修复方案

核心优化为并行请求接口一次性更新状态、移除冗余状态、使用函数式状态更新避免闭包问题,修复后代码如下:

const MainComponent=()=>{
  // 直接维护拖拽组件需要的columns状态,移除冗余的initialData
  const [columns, setColumns] = useState({
      ['Mapped Courses']: {
          name: 'Mapped Courses',
          items: []
      },
      ['Available Courses']: {
          name: 'Available Courses',
          items: []
      }
  });

  // 拖拽结束逻辑使用函数式更新获取最新状态,避免闭包旧值问题
  const onDragEnd = (result) => {
      if (!result.destination) return;
      const { source, destination } = result;
      setColumns(prevColumns => {
        if (source.droppableId !== destination.droppableId) {
            const sourceColumn = prevColumns[source.droppableId];
            const destColumn = prevColumns[destination.droppableId];
            const sourceItems = [...sourceColumn.items];
            const destItems = [...destColumn.items];
            const [removed] = sourceItems.splice(source.index, 1);
            destItems.splice(destination.index, 0, removed);
            return {
                ...prevColumns,
                [source.droppableId]: {
                    ...sourceColumn,
                    items: sourceItems
                },
                [destination.droppableId]: {
                    ...destColumn,
                    items: destItems
                }
            };
        } else {
            const column = prevColumns[source.droppableId];
            const copiedItems = [...column.items];
            const [removed] = copiedItems.splice(source.index, 1);
            copiedItems.splice(destination.index, 0, removed);
            return {
                ...prevColumns,
                [source.droppableId]: {
                    ...column,
                    items: copiedItems
                }
            };
        }
      })
  };

  useEffect(()=>{
    // 并行请求两个接口,一次性获取全部数据后更新状态,避免多次更新互相覆盖
    Promise.all([
      axios.get(`http://programsAPI/program`),
      axios.get('http://coursesAPI/courses')
    ]).then(([programRes, coursesRes]) => {
      setColumns({
        ['Mapped Courses']: {
            name: 'Mapped Courses',
            items: programRes.data.courses.map((course) => ({ id: course.id, content: course.slug }))
        },
        ['Available Courses']: {
            name: 'Available Courses',
            items: coursesRes.data.map((course) => ({ id: course._id, content: course.info.slug }))
        }
      })
    }).catch((err) => console.log(err))
  }, [programLoads])

  return ( 
      //HTML STARTS HERE
  )
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 21:27:04