Aurélien
Aurélien

Reputation: 1655

Display progress upload for multiple files with Axios and React

I am trying to display the progress for the files uploads in my React app.

First, I have created this function to upload multiple files:

  const [files, setFiles] = useState([])
  const saveDocuments = () => {
    try {
      files.forEach((file) => {
        axios.post("/api/documents", formData, {
          let formData = new FormData();
          formData.append("attached_file", file);
          formData.append("name", file.name);
          headers: {
            "X-CSRFTOKEN": getCookie("csrftoken"),
            "Content-Type": "multipart/form-data",
          },
          onUploadProgress: (progressEvent) => {
            const percentCompleted = Math.round(
              (progressEvent.loaded * 100) / progressEvent.total
            );
            file.progress = percentCompleted;
            console.log(percentCompleted);
          },
        });
      });
    } catch (e) {
      console.log(e);
    }
  };

With this code, I can see in the console the percentCompleted value.

And in my render function, I'm trying to display this progress value:

return(
  <ul>
    {files.map((file, index) => (
      <li key={index} >
        <div>{file.name}</div>
        <div>{file.progress} %</div>
      </li>
    ))}
  </ul>;  
)

The progress value does not display ; but the react dev tools shows the progress value in the state.

I guess I am not updating correctly the state of my file object. How can I deal with this? Thanks for helping.

Upvotes: 2

Views: 6226

Answers (1)

Aur&#233;lien
Aur&#233;lien

Reputation: 1655

So I found out the solution, I have to create a copy of my array files with a new key progress which has the value of percentCompleted

const saveDocuments = () => {
    try {
      files.forEach((file) => {

        axios.post("/api/documents", formData, {
          let formData = new FormData();
          formData.append("attached_file", file);
          formData.append("name", file.name);
          headers: {
            "X-CSRFTOKEN": getCookie("csrftoken"),
            "Content-Type": "multipart/form-data",
          },
          onUploadProgress: (progressEvent) => {
            const percentCompleted = Math.round(
              (progressEvent.loaded * 100) / progressEvent.total
            );
            // Create copy of file
            let newFile = file;
            // ... and set the progress
            newFile.progress = percentCompleted;
            // Create copy of files array
            let filesCopy = [...files];
            // Find the index of the file object
            let fileIndex = filesCopy.findIndex((el) => el.name === file.name);
            //... and replace the object with the new one containing the [progress] key
            filesCopy[fileIndex] = newFile;
            // Finally, update the state
            setFilesUploaded([...filesCopy]);
            file.progress = percentCompleted;
          },
        });
      });
    } catch (e) {
      console.log(e);
    }
  };

Then, the render function returns the new array containing objects with the progress key:

return(
  <ul>
    {filesUploaded.map((file, index) => (
      <li key={index} >
        <div>{file.name}</div>
        <div>{file.progress} %</div>
      </li>
    ))}
  </ul>;  
)

Upvotes: 3

Related Questions