首页 > 解决方案 > React Hooks FileReader。警告:unstable_flushDiscreteUpdates:React 已经在渲染时无法刷新更新

问题描述

选择文件后,我尝试在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[]>([]);

在onLoadCallback中使用readFile和更新状态的函数:

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);
        }
      }
    });    
  };

使用 Effect获取额外的文件数据

 useEffect(() => {
    if (files.length >0 && !loadedFileReader) {    
      getFileExif(files[0]);  
      return () => {
        files.forEach(file => URL.revokeObjectURL(file.preview));
      };    
    }
  }, [files]);


 return (
        <div>
          <FileWidgetDropzone
...

每次都会重新渲染该组件,然后从 getFileExif 函数调用状态更改(总共 4 次)。

当我放置调试器时;返回之前(...我收到一个错误浣熊控制台日志:警告 - index.js:1警告:unstable_flushDiscreteUpdates:React 已经呈现时无法刷新更新。

请帮助为此示例开发更有效的解决方案。

标签: reactjsreact-hooksfilereaderuse-effect

解决方案


使用 React Dropzone 时找到了解决方案。我使用承诺。

父组件:

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 });

推荐阅读