'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.
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:
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 1:[1]
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;
};
Solution 2:[2]
Maybe you can turn map to a for.
readAllFiles = async (AllFiles) => {
let results = [];
for (let file of AllFiles) {
const fileContents = await this.readFileContents(file);
results.push({ file, md5: SHA256(fileContents).toString() });
}
console.log(results, "result");
return results;
};
Solution 3:[3]
You can use Object.assign instead of spread syntax so instead of:
{ ...file, md5: SHA256(fileContents).toString() };
use this:
Object.assign(file, { md5: SHA256(fileContents).toString() });
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | Serdar |
| Solution 3 | Az.Youness |


