首页 > 解决方案 > 使用 React Drop zone 时,文件附件花费了太多时间

问题描述

我正在使用该react-dropzone库从浏览器中拖动或选择文件。

我有以下组件让用户选择多个文件。一切正常,除了如果用户选择更多文件,比如说 2 个或更多大小为 1 MB 的文件,则选择文件需要时间。如果文件数越多,选择用户选择的文件所需的时间就越多。根据我对react-dropzone文档的阅读,它会在上传后立即处理文件。所以我尝试设置 autoProcessQueue='false'。但没有运气。

我只想让用户在选择文件后和发送到后端服务器之前选择所有文件而不阻塞 30 或 40 秒。我进行了调试,并且在 DropZone 内部处理了所有文件之后达到了 setSelectedUserFiles()。我不确定是否有办法禁用它并让它作为表单的最终提交的一部分处理或单击按钮。如果我们不能达到同样的效果,有没有办法向用户显示正在附加文件的消息。任何帮助将不胜感激。

下面是我的反应组件

const SelectUserFiles = () => {
  const [userName,setUserName] = userState('TestUser')
  const [selectedUserFiles,setSelectedUserFiles] = userState([])
 
  const handleUserFileUpload = async (acceptedFiles) => {
      await setSelectedUserFiles(acceptedFiles)
    }
  
  return (
    <div className='myClass'>Select Files</div>
      <Dropzone
        //autoProcessQueue='false'
        accept={'.pdf'}         
        onDrop={acceptedFiles => handleUserFileUpload(acceptedFiles)}
      >…&lt;/Dropzone>
    </div>
    
    <MyButton>
    //logic to send the files to backend axios with the files selectedUserFiles 
    </MyButton>
  )
}

标签: javascriptreactjsreact-dropzone

解决方案


尝试这样的事情

  1. 创建仅发送文件的单独 api 组件,
  2. 您的具有 dropzone 的组件在本地管理文件上传,而不发送到服务器。您只需单击按钮并发送它。这个链接非常有帮助: https ://www.robinwieruch.de/react-hooks-fetch-data

第一个组件:

export const useApiCall = () => {
    const [data, setData] = useState({});

    const [selectedAllUserFiles, setSelectedAllUserFiles] = useState([]);

    const [isLoading, setIsLoading] = useState(false);
    const [isError, setIsError] = useState(false);

    useEffect(() => {
        const pushToserver = async () => {
            setIsError(false);
            setIsLoading(true);
            try {
                const formData = new FormData();
                Array.from(selectedAllUserFiles).forEach((file) => {
                    form.append('fileData', file);
                });

                const result = await axios.post(someUrl, formData);

                setData(result.data);
            } catch (error) {
                setIsError(true);
            }

            setIsLoading(false);
        };
        if (selectedAllUserFiles.length > 0) {
            pushToserver();
        }
    }, [selectedAllUserFiles]);

    //passing reference to the calling component

    return [{ data, isLoading, isError }, setSelectedAllUserFiles];
};

第二部分:

const SelectUserFiles = () => {
  const [userName,setUserName] = userState('TestUser')

  const [selectedUserFiles,setSelectedUserFiles] = userState([])

  //Ref from logical api call component
  const [{ data, isLoading, isError }, setSelectedAllUserFiles] = useApiCall();//new component

  const handleUserFileUpload = async (acceptedFiles) => {
        if (acceptedFiles) {
            acceptedFiles.map((file) => {
                setSelectedUserFiles((selectedUserFiles) => selectedUserFiles.concat(file));
                return selectedUserFiles;
            });
        }
      
      //await setSelectedUserFiles(acceptedFiles)
    }
  
  return (
    <div className='myClass'>Select Files</div>
      <Dropzone
        //autoProcessQueue='false'
        accept={'.pdf'}         
        onDrop={acceptedFiles => handleUserFileUpload(acceptedFiles)}
      >…&lt;/Dropzone>
    </div>
    
    //on click call api and pass collected user files all together
    <MyButton onClick={()=>setSelectedAllUserFiles(selectedUserFiles)}>
    //logic to send the files to backend axios with the files selectedUserFiles 
    </MyButton>
  )
}

推荐阅读