Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

185
Views
Async function overwrites array state when it should update only one item

I have a file upload component. The behavior is simple: I send one upload request to the back-end per file and as the upload progress increase, I have a bar that should increase with it.

I have a state that holds every selected file and their respective progress, as such:

interface IFiles {
    file: File;
    currentProgress: number;
}
const [selectedFiles, setSelectedFiles] = useState<IFiles[]>([]);

And when the user clicks the upload button, this function will be triggered and call uploadFile for each file in my array state.

const sendFilesHandler = async () => {
        selectedFiles.map(async (file) => {
                const fileType = file.file.type.split('/')[0];
                const formData = new FormData();
                formData.append(fileType, file.file);
                formData.append('filename', file.file.name);
                await uploadFile(formData, updateFileUploadProgress);
        });
    };

Here is what the uploadFile function looks like.

const uploadFile = async (body: FormData, setPercentage: (filename: string, progress: number) => void) => {
    try {
        const options = {
            onUploadProgress: (progressEvent: ProgressEvent) => {
                const { loaded, total } = progressEvent;
                const percent = Math.floor((loaded * 100) / total);
                const fileName = body.get('filename')!.toString();

                if (percent <= 100) {
                    setPercentage(fileName, percent)
                }
            }
        };

        await axios.post(
            "https://nestjs-upload.herokuapp.com/",
            body,
            options
        );

    } catch (error) {
        console.log(error);
    }
};

As you can see, when uploadProgress is triggered it should inform call setPercentage function, which is:

const updateFileUploadProgress = (fileName: string, progress: number) => {
        console.log('Entrada', selectedFiles);
        const currentObjectIndex = selectedFiles.findIndex((x) => fileName === x.file.name);
        const newState = [...selectedFiles];
        newState[currentObjectIndex] = {
            ...newState[currentObjectIndex],
            currentProgress: progress,
        };
        setSelectedFiles(newState);
        console.log('Saída', newState);
    };

And this function should only update the object of my state array where the filenames match. However, it is overriding the whole thing. The behavior is as follows:

enter image description here

So it seems that everything is fine as long as I am updating the same object. But in the moment onUploadProgress is triggered to another object, selectedFiles states becomes its initial state again. What am I missing to make this work properly?

about 4 years ago · Juan Pablo Isaza
1 answers
Answer question

0

I am not sure what is the exact reason behind this behaviour but I came up with the below unexpectedly simple solution after spending 3 hours straight on it.

const updateFileUploadProgress = (fileName: string, progress: number) => {
  setSelectedFiles(prevState => {

    const currentObjectIndex = prevState.findIndex((x) => fileName === x.file.name);
    const newState = [...prevState];

    newState[currentObjectIndex] = {
      ...newState[currentObjectIndex],
      currentProgress: progress,
    };

  return newState;
  })
};

I was able to mimic your problem locally, and solved it with the above approach. I think it was because the function (for some reason) still referenced the initial state even after rerenders.

about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!