React Hooks FileReader。警告:unable_flushDiscreteUpdates:React已经渲染时无法刷新更新

时间:2019-12-12 19:21:54

标签: reactjs react-hooks filereader use-effect

选择文件后,我尝试在 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已经存在时无法刷新更新呈现。

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

1 个答案:

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