繁体   English   中英

React Dropzone - onDrop 回调中的异步 function 不更新 state

[英]React Dropzone - async function in onDrop callback doesn't update state

我正在尝试将 react-dropzone onDrop与 useCallback function 一起使用来更新放置到该区域的文件数组并触发上传。 我的代码如下所示:

const [files, setFiles] = useState([]);

...

const onDrop = useCallback((acceptedFiles) => {
  setFiles(acceptedFiles);
  handleFileUpload();
}, []);

const {
  getRootProps,
  getInputProps,
  isDragActive,
} = useDropzone({ onDrop });

handleFileUpload是一个异步 function,它使用 Fetch API。当我尝试在这个方法中记录files数组时,它似乎是空的,即使我在运行这个 function 之前更新了 state。

const handleFileUpload = async () => {
  console.log(files); // <- returns empty array
}

我还尝试设置不同的变量来指示上传是否已开始等,但是更改此方法中的值根本不会更新我的组件的 state。 甚至可以在这样的回调中使用异步 function 吗? 我应该在其他地方触发文件上传吗? 我觉得我不太理解这里的概念。

在您的代码退出和/或放弃控制之前,您的 state 不会更新。 即在您调用setFiles()之后, files变量将仍然是 STALE,直到代码返回到事件循环。

只需将接受的文件传递到 function。

const onDrop = useCallback((acceptedFiles) => {
  setFiles(acceptedFiles); // <-- that won't update right away
  handleFileUpload(acceptedFiles);
}, []);

更新

这是我的一个项目的片段。 我只是像你一样把拖放的文件塞进state。 这会导致组件重新呈现,当它重新呈现时,我会在挂钩中捕获更新后的文件 state,异步解析文件并返回数据——然后组件会使用这些数据。 该组件显示 UI 状态 - 如果设置了fileToImport并且dataToImport尚不可用,则导入,等等......

// MyComponent.tsx
const MyComponent = () => {
  const [fileToImport, setFileToImport] = useState<File | undefined>()
  const [dataToImport, dataToImportError] = useReadFileData(fileToImport)

  const onDrop = useCallback(acceptedFiles => {
    setFileToImport(acceptedFiles[0])
  }, [])


//useREadFileData.ts hook
import { useEffect, useState } from 'react'

const useReadFileData = (file: File | undefined): [any[], string | undefined] => {
  const [rows, setRows] = useState<unknown[]>([])
  const [error, setError] = useState<string>()

  useEffect(() => {
    async function parseFile(file: File) {
      try {
        // snip
        setRows(rows)
      } catch (error: any) {
        if (typeof error === "object") {
          setError(error?.message ?? "Error parsing file")
        }
      }
    }
    // only if we have a file to parse
    if (file) {
      parseFile(file)
    }
  }, [file, setError, setRows])

  return [rows, error]
}

export default useReadFileData

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM