繁体   English   中英

setState在Array.map函数中仅执行一次

[英]setState is only executing once in Array.map function

我有一个用于遍历新上传文件的Array.map函数。

由于用户可以多次上传文件,因此必须将文件一起添加到一个阵列中。

因此,我正在使用以下代码

onFileSelect = e => {
    //FileList to array
    const files = [...e.target.files];

    files.map(file => {
        this.setState({ invoices: [...this.state.invoices, file]})
    });
}

问题在于setState仅在最后一项上执行。 因此,如果nuser选择5个文件,则只有最后一个进入状态。

一种可能的解决方案是获取扩展数组,推送新文件并在map函数之外执行一个setState,但是我想知道为什么或如何将多个setStates集成到一个map函数中。

这工作

onFileSelect = e => {
    //FileList to array
    const files = [...e.target.files];

    const invoiceArr = this.state.invoices;

    files.map(file => {
        invoiceArr.push(file)
    });

    this.setState({invoices: invoiceArr});
}

那是因为React会批处理状态,这意味着setState实际上并没有设置状态,而是将状态转换添加到队列中,然后在某个时间执行。 因此,在您的情况下,队列将如下所示(伪代码):

original -> original + files[0]
original -> original + files[1]
original -> original + files[2]
// flattened to:
original -> original + files[2]

如您所见,状态互不依赖。 因此,react只会采用最后一个状态,并且您只会看到最后一个文件。 相反,您可以使一个状态依赖于前一个状态:

files.forEach(file => {
    this.setState(previous => ({
        invoices: [...previous.invoices, file]
    }));
});

这导致队列看起来像:

original -> original + files[0]
previous -> previous + files[1]
previous -> previous + files[2]
// flattened to
original -> original + files[0] + files[1] + files[2]

但是实际上您可以一步添加所有文件:

this.setState(previous => ({ invoices: previous.invoices.concat(files) }));

TLDR:如果状态取决于先前的状态,请不要设置状态。 setState内的this.state被禁止,并且只能“偶然”工作。

第一个循环的问题是每次迭代都覆盖现有项目,并且由于setState是异步的,因此这样做是不安全的

为什么不这样做呢?

onFileSelect = e => {
  //FileList to array
  const files = [...e.target.files];
  this.setState({ invoices: []})

  files.each(file => this.state.invoices.push(file)});
}

第二个选项似乎是正确的。
如果要返回新数组,应使用map函数。
您还可以使用reduce

onFileSelect = e => {

  const files = [...e.target.files];
  const invoiceArr = this.state.invoices;

  let invoicesUpdated = files.reduce((acc, file) => {
    acc.push(file);
    return acc;
  }, invoiceArr);

  this.setState({invoices: invoicesUpdated});
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM