javascriptreactjsshallow-copy

Why is the JavaScript spread notation not working here


I am learning React and have this simple problem I can't solve.

I created a Codesandbox

Here in the image: the file is a key-value array like the image show.

enter image description here

After this code below has run:

return { ...file, md5: SHA256(fileContents).toString() };

Then the result is that key value pairs are removed like this image show:

enter image description here

As you see the file now only contains path and md5 and everything else is gone.

I know this got to do with maybe shallow copy principle but I have search for a solution but can't understand how to fix this.

const FilePicker = ({ setNewFileForValidation }) => {
    const readFileContents = async file => {
        return new Promise((resolve, reject) => {
            const fileReader = new FileReader();
            fileReader.onload = () => {
                resolve(fileReader.result);
            };
            fileReader.onerror = reject;
            fileReader.readAsBinaryString(file);
        });
    };
    const readAllFiles = async AllFiles => {
        const results = await Promise.all(
            AllFiles.map(async file => {
                const fileContents = await readFileContents(file);
                return { ...file, md5: SHA256(fileContents).toString() };
            }),
        );
        console.log(results, 'resutls');
        return results;
    };

    function onDrop(acceptedFiles, rejectedFiles) {
        readAllFiles(acceptedFiles).then(result => {
            setNewFileForValidation(result);
        });
    }
    return <Dropzone onDrop={onDrop} />;
};

The file is coming from react-dropzone and contains the result from the file picker. Maybe that is the reason this spread copy does not work?


Solution

  • File is a special object whose properties are not enumerable. Therefore the spread syntax is not working expectedly. You need to clone the File object using the File constructor.

    readAllFiles = async (AllFiles) => {
        const results = await Promise.all(
          AllFiles.map(async (file) => {
            const fileContents = await this.readFileContents(file);
            // THIS IS THE PROBLEM
            //return { ...file, md5: SHA256(fileContents).toString() };
            file = new File([file], file.name, { type: file.type })
            file.md5 = SHA256(fileContents).toString();
            return file;
          })
        );
        console.log(results, "result");
        return results;
      };