使用 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)}
      >…</Dropzone>
    </div>
    
    <MyButton>
    //logic to send the files to backend axios with the files selectedUserFiles 
    </MyButton>
  )
}

解决方法

尝试这样的事情

  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,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)}
      >…</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>
  )
}