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

React中点击提交按钮时如何保证useState存储的值为最新数据

根因分析

提交旧状态问题核心不是useState异步更新导致的,而是闭包捕获问题:
你用空依赖的useEffect仅在组件首次渲染时将saveDisplayedVideo函数挂载到childRef上,这个函数捕获了首次渲染时的displayedVideoDataList、videoDataList初始值。后续组件状态更新后,重新生成的saveDisplayedVideo函数不会同步更新到childRef中,所以调用保存函数时永远拿到的是初始状态值。

正常用户交互(比如拖拽完成后间隔一段时间再点击保存)时,useState的批处理更新早就执行完成,状态已经是最新的,只要能拿到最新的状态引用就不会出现旧数据问题。

可行解决方案

方案1:更新ref绑定逻辑,保持函数为最新版本(推荐,改动最小)

用useCallback包裹保存函数,关联对应状态作为依赖项,再修改useEffect的依赖项为包裹后的保存函数,保证ref中始终绑定最新版本的保存函数:

import { useCallback } from 'react';

// 用useCallback包裹,依赖项为函数内用到的所有状态
const saveDisplayedVideo = useCallback(async () => {
  const jsonData = JSON.parse(JSON.stringify(displayedVideoDataList));
  console.log(jsonData);
  console.log(displayedVideoDataList);
  console.log(videoDataList);
  // 补充提交后端的逻辑即可
}, [displayedVideoDataList, videoDataList]);

// useEffect添加saveDisplayedVideo作为依赖,函数更新时同步刷新ref
useEffect(()=>{
  props.childRef.current = saveDisplayedVideo;
}, [saveDisplayedVideo]);

方案2:用ref同步最新状态,提交时直接从ref取值

如果不想频繁更新ref绑定的函数,可以单独用ref存储最新的状态值,状态更新时自动同步到ref,保存函数直接从ref取数即可:

import { useRef } from 'react';

const [videoDataList, setVideoDataList] = useState(props.videoData);
const [displayedVideoDataList, setDisplayedVideoDataList] = useState([]);
// 新增ref存储最新状态
const latestStateRef = useRef({
  videoDataList,
  displayedVideoDataList
});

// 状态更新时同步到ref
useEffect(() => {
  latestStateRef.current = {
    videoDataList,
    displayedVideoDataList
  };
}, [videoDataList, displayedVideoDataList]);

// 保存函数直接从ref取最新值,不需要依赖状态
async function saveDisplayedVideo(){
  const { videoDataList, displayedVideoDataList } = latestStateRef.current;
  const jsonData = JSON.parse(JSON.stringify(displayedVideoDataList));
  console.log(jsonData);
  console.log(displayedVideoDataList);
  console.log(videoDataList);
}

// 这里useEffect可以保持空依赖不变
useEffect(()=>{
  props.childRef.current = saveDisplayedVideo;
},[]);

方案3:同事件回调内提交直接用计算的新值(仅适用于状态更新和提交在同一回调的场景)

如果你的状态更新和提交操作在同一个事件回调中触发,可以不用等待useState更新,直接用你计算出来的新值提交,比如:

// 示例逻辑,你的拖拽+延时提交的场景不适用该方案
function handleToggleAndSubmit() {
  const newStatus = !status;
  setStatus(newStatus);
  // 直接用新计算的newStatus提交,不需要依赖state
  submitData(newStatus);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 20:36:00