为什么在 setstate 之后反应没有重新渲染

Why is react is not rerendering after setstate

在下面的反应代码中,我试图通过更新字典来更改按钮颜色。不幸的是,除非我强制重新渲染,否则它不起作用。

const jsonFromDatabase = [{ "id": 1, "name": "Ka" },
{ "id": 2, "name": "Erd" }];

const json = [{ "id": 2, "name": "Ka" },
{ "id": 3, "name": "Erd" }];
class ControllableButton extends React.Component {
  constructor() {
    super();
    this.state = {
      color_black: true,
      datasetForDisplay: json,
      datasetForStorage: jsonFromDatabase
    }
  }

  onClickGroupToUpdate = (cell, row, rowIndex) => {
    let toAdd = { "id": row.id, "name": row.name }
    this.setState((prevState, props) => {
      datasetForStorage: prevState.datasetForStorage.push(toAdd)
    })
    console.log("updated the database")
    console.log(this.state.datasetForStorage)
    // this.forceUpdate()
  }

  onClickGroupSelected = (cell, row, rowIndex) => {
  }

  // cellButton should be modified each time of click
  cellButton = (cell, row, enumObject, rowIndex) => {
    let theButton
    let inDB = false
    console.log(row)
    for (var group in this.state.datasetForStorage) {
      if (this.state.datasetForStorage[group].id == row.id) {
        inDB = true
      }
    }
    if (inDB) {
      theButton = <button style={{ backgroundColor: "blue" }}
        type="button"
        onClick={() => this.onClickGroupSelected(cell, row, rowIndex)}>
        In database
               </button>
      console.log('already in database' + row.id)
    } else {
      theButton = <button style={{ backgroundColor: "red" }}
        type="button"
        onClick={() => this.onClickGroupToUpdate(cell, row, rowIndex)}>
        Update database
               </button>
      console.log('not in  database' + row.id)
    }
    return theButton
  }

  render() {
    return (
      <BootstrapTable data={this.state.datasetForDisplay} >
        <TableHeaderColumn isKey dataField='id' width='100'>ID</TableHeaderColumn>
        <TableHeaderColumn dataField='name' width='300'>Group Name</TableHeaderColumn>
        <TableHeaderColumn dataField='button' width='100' dataFormat={this.cellButton}>Generate Group Page</TableHeaderColumn>
      </BootstrapTable>
    );
  }
}

ReactDOM.render(<ControllableButton />, document.getElementById('app'));

以上代码不会在每次单击更新组后重新呈现,除非我强制更新。你能帮我弄清楚我做错了什么吗?

当您将 setState() 与更新函数一起使用时,该函数需要 return 一个表示要合并的数据的对象。你没有 returning 任何东西,所以你的更新函数实际上 returns undefinedhttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions#Returning_object_literals

另一个问题是你应该复制你所在州的数组,将新数据推入其中,然后用它来更新。永远不要直接改变你所在州的内容。

onClickGroupToUpdate = (cell, row, rowIndex) => {
    let toAdd = { "id": row.id, "name": row.name }
    this.setState((prevState, props) => {
      // Copy the array that you have in state
      let datasetForStorageCopy = prevState.datasetForStorage.slice();
      datasetForStorageCopy.push(toAdd)
      // Return a new object describing the state change
      return {datasetForStorage: datasetForStorageCopy}
    })
    console.log("updated the database")
    console.log(this.state.datasetForStorage)
    // this.forceUpdate()
}

您没有使用 setState correctly and on top of that you are mutating it, which you shouldn't

而不是这个:

this.setState((prevState, props) => {
  datasetForStorage: prevState.datasetForStorage.push(toAdd)
})

您可以只传递一个普通对象:

this.setState({
  datasetForStorage: [...this.state.datasetForStorage,toAdd]
})

或者像你一样传递函数,但注意对象周围的 () 所以我们实际上 return 一个对象:

this.setState((prevState, props) => ({
  datasetForStorage: [...prevState.datasetForStorage,toAdd]
}))

箭头函数是 return 隐式但不会 return 如果你使用花括号

() => {}

所以你必须用括号括起来

() => ({})

我已经使用了 spread syntax 来帮助我们轻松地创建一个新数组。