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

上传同一文件时onUpload未触发,是否是useCallback和useEffect使用错误?

问题根因

你遇到的重复上传同名文件不触发onUpload的问题,和useCallback、useEffect的使用无关,根因为原生文件选择框的默认特性:当用户选中的文件路径与input当前的value属性存储的路径完全一致时,onChange事件不会触发,自然不会走到后续的setFiles和上传逻辑。

修复方案

你只需要对现有代码做少量调整即可解决问题,同时优化你提到的调用逻辑问题:

核心修改点

  • 每次打开文件选择器前,主动清空file input的value,保证即使选择同一文件也能触发onChange
  • 可选择移除冗余的files状态,减少不必要的组件重渲染
  • 调整onUpload为接收文件列表参数,简化useCallback依赖

修复后完整代码

export const UploadAssets = (props) => {  
  const fileInput = useRef<HTMLInputElement>(null);

  useEffect(() => {
    // 原有逻辑保持不变
  }, []);

  const onChooseFile = (e) => {
    e.preventDefault();
    if (fileInput?.current) {
      props.options.onStart();
      // 新增:清空input value,解决同文件二次选择不触发问题
      fileInput.current.value = '';
      fileInput.current.click();
    }
  }

  const onUpload = useCallback((files: FileList) => {
    if (!files) return false;
    const formData = new FormData();
    for (let i = 0; i < files.length; i++) {
      const file = files[i];
      formData.append(file.name, file);
    }
    const xhr = new XMLHttpRequest();
    xhr.open('post', myUrl, true);
    xhr.send(formData);
    return true;
  }, []);

  const onChangeFile = (e) => {
    e.preventDefault();
    const selectedFiles = e.target.files;
    if (selectedFiles) {
      props.options.onChooseFile(selectedFiles);
      // 直接调用上传,不需要经过state中转
      onUpload(selectedFiles);
    }
  }

  return (
    <div>
      <button onClick={onChooseFile}>Upload File</button>
      <input type="file" ref={fileInput} onChange={onChangeFile} hidden/>
    </div>
  );
}
额外说明

如果你需要保留files状态用于页面展示(比如显示已选文件列表),也可以不删除files状态和对应的监听useEffect,只需要在onChooseFile方法里加fileInput.current.value = ''这一行即可解决重复上传的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 21:57:03