簡體   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