在React中修改和复制文件对象

时间:2018-06-20 08:10:07

标签: javascript arrays reactjs

我在React中有一个组件,在其中我向它传递了一个文件对象。我对这个File对象做了很多事情,但是我也通过执行this.props.file.color = #000

向File对象添加了新的值。

在我的组件中,我有一个函数可以触发父函数来复制文件对象

组件

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对象中的名称。

有什么建议吗?

2 个答案:

答案 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);