选择文件后,我尝试在 FileWidgetDropzone 上使用 FileReader 。
我在 onLoadCallback 中使用了一个函数:
const readFile = (file: any, onLoadCallback: any) => {
var reader = new FileReader();
reader.onload = onLoadCallback;
reader.readAsArrayBuffer(file);
};
我使用State存储来自 onLoadCallback 函数的结果数据(fileMetadata):
const [loadedFileReader, setLoadFileReader] = useState(false);
const [fileMetadata, setFileMetadata] = useState<IFileMetadata>(
new FileMetadataValues()
);
const [files, setFiles] = useState<any[]>([]);
使用 readFile 并在 onLoadCallback 内更新状态的函数:
const getFileExif = (file: any) => {
setLoadFileReader(true);
readFile(file, function(e: any) {
const data = ... e.target.result;
if (data) {
var model = new FileMetadataValues();
...
setFileMetadata(model);
setLoadFileReader(false);
}
}
});
};
使用效果以获取其他文件数据
useEffect(() => {
if (files.length >0 && !loadedFileReader) {
getFileExif(files[0]);
return () => {
files.forEach(file => URL.revokeObjectURL(file.preview));
};
}
}, [files]);
return (
<div>
<FileWidgetDropzone
...
每次重新渲染此组件,然后从getFileExif函数调用状态更改(总共4次)。
当我将 debugger; 放在返回之前(...时,我收到了错误的Coon控制台日志:警告-index.js:1 警告:unable_flushDiscreteUpdates:当React已经存在时无法刷新更新呈现。
请帮助为该示例开发更有效的解决方案。
答案 0 :(得分:0)
使用React Dropzone时找到了解决方案。我使用Promises。
父组件:
const [files, setFiles] = useState<any[]>([]);
const [filesMetadata, setFilesMetadata] = useState<any[]>([]);
子组件:
const getFilesMetadata = (acceptedFiles: object[]) => {
const files = [...acceptedFiles];
parseMeta(files);
};
files.forEach((file: any) => {
let promise = new Promise(resolve => {
const reader = new FileReader();
reader.onabort = () => console.log("file reading was aborted");
reader.onerror = () => console.log("file reading has failed");
reader.onload = () => {
...
resolve(model);
};
reader.readAsArrayBuffer(file);
});
promises.push(promise);
});
Promise.all(promises).then((data) => {
setFilesMetadata(
data.map((fileMeta: FileMetadataValues) =>
Object.assign(fileMeta, fileMeta)
)
);
});
const onDrop = useCallback(
acceptedFiles => {
setFiles(
acceptedFiles.map((file: object) =>
...
)
);
getFilesMetadata(acceptedFiles);
},
[setFiles, getFilesMetadata]
);
const { getRootProps, getInputProps, isDragActive } = useDropzone({ onDrop });