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

React中window.confirm回调内useState存储的上传文件状态被清空问题

问题原因

这是React的闭包陷阱导致的:

  • 你的useEffect仅将halfFilledForm作为依赖项,仅当halfFilledForm发生变化时,这个effect才会重新执行
  • effect执行时会捕获当前作用域内的所有状态值,你首次执行effect时files还是初始的空数组[]
  • 后续你调用setFiles更新文件列表时,只要halfFilledForm没有变化,effect就不会重新运行,history.block绑定的回调永远引用的是首次执行时捕获的旧files值,所以打印出来一直是空数组。

解决方案

方案1:把files加入useEffect的依赖数组

每次files更新时,effect都会重新执行,重新注册最新的history.block回调,就能拿到最新的files值,代码修改如下:

useEffect(() => {
  if (halfFilledForm) {
    const unblock = history.block((_) => {
      if (window.confirm("Do you want to save the Story Idea as Draft?")) {
         console.log(files) // 可以拿到最新的files
         saveAsDraft();
      }
      return true;
    });
    return () => {
      unblock();
    };
  }
// 把files加入依赖数组
}, [halfFilledForm, files]);

方案2:用useRef存储最新的files状态

useRef的current属性是可变的,不受闭包限制,可以随时拿到最新值:

const [files, setFiles] = useState([]);
// 新增ref同步files的最新值
const filesRef = useRef(files);
// 监听files变化,自动更新ref
useEffect(() => {
  filesRef.current = files;
}, [files]);

// 原来的history.block useEffect不用改依赖,回调里读ref即可
useEffect(() => {
if (halfFilledForm) {
  const unblock = history.block((_) => {
    if (window.confirm("Do you want to save the Story Idea as Draft?")) {
       console.log(filesRef.current) // 直接读ref的current拿到最新值
       saveAsDraft();
    }
    return true;
  });
  return () => {
    unblock();
  };
}}, [halfFilledForm]);

方案3:将saveAsDraft改造为接收files作为入参

如果saveAsDraft逻辑允许,你可以在调用时主动把最新的files作为参数传入,配合上述两种方案使用即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 06:54:05