Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
228 views
in Technique[技术] by (71.8m points)

javascript - File attachment is taking too much time when using React Drop zone

I am using the react-dropzone library to drag or select files from the browser.

I have the below component to let the user select multiple files. Everything works except that if the user chooses more files let say 2 or more files with size 1 MB, the selection of documents is taking time. If the number of files is more, the more time it takes to selected the user-selected files. As per my reading of the react-dropzone docs, it processes files as soon as it uploads. So I tried setting autoProcessQueue='false'. but no luck.

I just want to let the user select all the files without blocking for 30 or 40 secs after selecting files, and before send to the backend server. I did the debug and the setSelectedUserFiles() is reached after all the files are processed internally by the DropZone. I am not sure if there is a way to disable it and let it process as part final submission of the form or click on the button. In case if we can't achieve the same, is there a way to show the message to the user that files are being attached. Any help will be appreciated.

Below is my react component

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>
  )
}
question from:https://stackoverflow.com/questions/66051003/file-attachment-is-taking-too-much-time-when-using-react-drop-zone

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Try something like this

  1. Create separate api component that only send files,
  2. Your component that has dropzone manages file upload locally without sending to the server. You only click the button and send it. this link was very helpful: https://www.robinwieruch.de/react-hooks-fetch-data

first component:

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

Second component:

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...