[英]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.