【问题标题】:Why is the JavaScript spread notation not working here为什么 JavaScript 扩展符号在这里不起作用
【发布时间】:2021-05-03 19:18:48
【问题描述】:

我正在学习 React,但遇到了一个我无法解决的简单问题。

我创建了一个Codesandbox

在图片中:file 是一个键值数组,如图片所示。

以下代码运行后:

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

然后结果是键值对被删除,如下图所示:

如您所见,该文件现在只包含 pathmd5,其他所有内容均已消失。

我知道这可能与浅拷贝原理有关,但我正在寻找解决方案,但不知道如何解决。

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} />;
};

file 来自react-dropzone,包含来自文件选择器的结果。也许这就是这个传播副本不起作用的原因?

【问题讨论】:

  • 也许 File 是某种特殊的对象?并非每个对象的每个属性都是可枚举的。你能通过return (file.md5=SHA256(fileContents).toString(),file); 避免这个问题吗?
  • @loop 是的,它可以使用 return (file.md5=SHA256(fileContents).toString(),file); 工作,但是我认为我会改变状态,不确定
  • 我不确定.map 是否可以与async/await 一起使用。
  • 请以文字形式提供数据,而不是文字图片。有视觉障碍的人和搜索引擎机器人无法阅读您的图片。

标签: javascript reactjs shallow-copy


【解决方案1】:

文件是一个特殊的对象,它的属性是不可枚举的。因此传播语法没有按预期工作。您需要使用 File 构造函数 clone the File object

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;
  };

【讨论】:

    【解决方案2】:

    也许你可以把 map 转成 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;
    };
    

    【讨论】:

      【解决方案3】:

      您可以使用Object.assign 代替展开语法,因此可以代替:

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

      使用这个:

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

      【讨论】:

        猜你喜欢
        • 2016-08-21
        • 2012-01-15
        • 2012-07-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-05-16
        相关资源
        最近更新 更多