Reputation: 6281
I have a component in React where I pass it a file object. I do various things with this File object, but I am also adding new values to the File object by doing this.props.file.color = #000
Within my component, I have a function that triggers a parent function to duplicate the File Object
Component
duplicate =()=> {
this.props.file.color = this.getColor();
console.log(this.props.file)
//File Object
// -- color: #cb0000
// -- name:filename.png
this.props.duplicate(this.props.file);
}
As you can see, it has added a color value to the File Object, and the filename is correct. I then pass this data back to a duplication function in my parent
Parent
i is the array index, a is the File Object
duplicate(i, a) {
let dupeArr = a;
const arr = [...this.state.files];
const index = i + 1;
let name = dupeArr.name.slice(0, -4);
Object.defineProperty(dupeArr, 'name', { writeable: true, value: `${name}-${a.color}.png`})
arr.splice(index, 0, a);
console.log(arr)
// 2x File Objects
// Original file
// -- #cb0000 (Correct)
// -- filename-#cb0000.png (Incorrect, why is it changing this name?)
//Duplicated file
// -- -- #cb0000 (Correct)
// -- filename-#cb0000.png (Correct)
this.setState({
files: arr
})
}
What I am doing here is taking the File Object that was passed to it, defining the name of that File Object and then splicing into the existing files array before setting it as state.
For some reason though, when I define the name property, it is changing the name in both the original entry in the array, as well as my new File Object.
Any suggestions?
Upvotes: 1
Views: 1189
Reputation: 4318
The reason is that you are mutating the original file object, and it is still being referenced in this.state.files
. You are making a copy of your files array here:
const arr = [...this.state.files];
But this does not in fact produce copies of the file objects contained in the array. They are still referencing the original objects.
You are running into issues because you are mutating the file object at this line and your copied array is still referencing the original object:
Object.defineProperty(dupeArr, 'name', { writeable: true, value: `${name}-${a.color}.png`})
Assuming you are converting the File object to a normal JS Object (like you mentioned in your answer) and then only passing the index of the object you want to modify to duplicate
:
duplicate = (index) => {
let filesCopy = [...this.state.files];
let objToModify = filesCopy[index];
let objModified = {...objToModify, name: /* somename */, preview: /* some preview */ }
filesCopy.push(objToModify);
this.setState({ files: filesCopy });
}
Upvotes: 1
Reputation: 6281
The problem was that when the files were uploaded, the were File Objects and it is not possible to copy a File Object.
The easy solution was to take @deowk's duplication solution, but also to convert the File Objects to a JSON Object on upload, only taking what I needed:
onDrop(files) {
let f = files.map(file => ({
name: file.name,
preview: file.preview
}));
this.setState({
files: this.state.files.length > 0 ? [...this.state.files, ...f] : f,
});
}
Upvotes: 1