我在React中有一个组件,在其中我向它传递了一个文件对象。我对这个File对象做了很多事情,但是我也通过执行this.props.file.color = #000
在我的组件中,我有一个函数可以触发父函数来复制文件对象
组件
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);
}
如您所见,它已为文件对象添加了一个颜色值,并且文件名正确。然后,我将这些数据传回到我父母的复制函数中
父母
i是数组索引,a是文件对象
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
})
}
我在这里要做的是获取传递给它的文件对象,定义该文件对象的名称,然后在将其设置为状态之前拼接到现有的文件数组中。
但是由于某种原因,当我定义name属性时,它将更改数组中原始条目以及新File对象中的名称。
有什么建议吗?
答案 0 :(得分:1)
原因是您正在变异原始文件对象,并且仍在this.state.files
中对其进行引用。您正在这里复制文件数组:
const arr = [...this.state.files];
但这实际上并不会产生数组中包含的文件对象的副本。他们仍在引用原始对象。
您遇到了问题,因为您正在更改此行的文件对象,而您复制的数组仍在引用原始对象:
Object.defineProperty(dupeArr, 'name', { writeable: true, value: `${name}-${a.color}.png`})
假设您要将File对象转换为普通的JS对象(如您在回答中提到的那样),然后仅将要修改的对象的索引传递给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 });
}
答案 1 :(得分:1)
问题是,当文件上传时,文件对象是文件对象,并且无法复制文件对象。
简单的解决方案是采用@deowk的复制解决方案,而且还要在上载时将文件对象转换为JSON对象,仅采取我需要的方式即可:
You have to define request delay
----> requestDelay: 400
var options = {
url: function (phrase) {
return "api/getData";
},
getValue: function (element) {
return element['name'];
},
ajaxSettings: {
dataType: "json",
method: "POST",
data: {
dataType: "json"
}
},
preparePostData: function (data) {
data.phrase = $(".name").val();
return data;
},
match: {
enabled: true
},
requestDelay: 400
};
$(".name").easyAutocomplete(options);