为什么反应不会在setstate之后重新出现

时间:2017-12-13 21:06:22

标签: reactjs 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'));

每次点击更新组后,上面的代码都不会重新渲染,除非我强制更新。你能帮我弄清楚我在这里做错了吗?

2 个答案:

答案 0 :(得分:1)

当您使用带有更新程序功能的setState()时,该函数需要返回一个表示要合并的数据的对象。您没有返回任何内容,因此您的更新程序功能实际返回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()
}

答案 1 :(得分:1)

您没有正确使用setState,而且您正在改变它which you shouldn't

而不是:

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

你可以传递一个普通的对象:

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

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

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

箭头函数隐式返回,但如果使用大括号

则不会返回
() => {}

所以你必须用括号包装它们

() => ({})

我使用了spread syntax来帮助我们轻松创建新数组。