React:为什么在调用setState之前尝试以不可变的方式更改状态时更改状态

时间:2018-07-19 09:50:39

标签: javascript reactjs ecmascript-6

当我尝试在React中更改状态不变时,它正在更改状态,而我打电话给setstate,这使我困惑了三天。

这是我在onClick事件中调用的方法:

share = (indexFolder) => {
    console.log(this.state.folderInfo);
    const updateFolderInfo = [...this.state.folderInfo];
    updateFolderInfo[indexFolder].isProcessing = false; 

    //state**is already changed**strong text** when console **
    console.log(this.state.folderInfo);

    this.setState({
            folderInfo : updateFolderInfo,
    })
    // the setState call do not take effect here 
}

这是执行方法的地方:

<Folder key={folder._id}
        sharing={this.state.folderIsProcessing}
        folder={folder} 
        delete={() => this.delete(index)}
        share={() => this.share(index)} />
//I'm passing share function as props in here ^ , and use it on 
//click event in the Folder component . 

有人建议为什么会这样吗?

3 个答案:

答案 0 :(得分:1)

这里的问题是,通过执行const updateFolderInfo = [...this.state.folderInfo];,您可以有效地制作folderInfo副本。

这意味着,如果您在updateFolderInfo内修改任何对象或数组项,那么您还将在原始folderInfo数组内修改相同的对象/数组。

假设folderInfo内仅包含JSON,以下是使用JSON.stringifyJSON.parse创建深层副本的潜在解决方案:

share = indexFolder => {
  const updatedFolderInfo = JSON.parse(JSON.stringify(this.state.folderInfo));
  updatedFolderInfo[indexFolder].isProcessing = false; 

  this.setState({ folderInfo : updatedFolderInfo });
}

这是一个小示例,以简化的方式向您展示您当前正在做的事情:

array1 = [{id: 1}, {id: 2}, {id: 3}]
array2 = [...array1]

array2[0].id = 100

array2
// [{id: 100}, {id: 2}, {id: 3}]

array1
// [{id: 100}, {id: 2}, {id: 3}]

您可以找到有关浅克隆和深克隆here的更多信息。

答案 1 :(得分:0)

您已经将函数绑定到上面的范围。尝试像这样更改它。

share = (indexFolder) => {
      console.log(this.state.folderInfo);
      const updateFolderInfo = [...this.state.folderInfo];
      updateFolderInfo[indexFolder].isProcessing = false; 
      //state**is already changed**strong text** when console **
       console.log(this.state.folderInfo);
      this.setState({
            folderInfo : updateFolderInfo,
      })
      // the setState call do not take effect here 
    }

<Folder  key={folder._id}
                                sharing={this.state.folderIsProcessing}
                                folder={folder} 
                                delete={this.delete(index)}
                                share={this.share(index)}
        />

答案 2 :(得分:0)

提供的信息太少,但是尝试以其他方式使用setState:

var ss= SpreadsheetApp.getActiveSpreadsheet();
var ss1=ss.getSheetByName("stopwatch"); 


function timerstart() {  

  for(i=0;i<10000;i++){

   Utilities.sleep(10);
   ss.getRange('B6').setValue(i);

 }
}

关于setState的异步性质:https://medium.com/@wereHamster/beware-react-setstate-is-asynchronous-ce87ef1a9cf3