为什么在 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 undefined
。 https://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 来帮助我们轻松地创建一个新数组。
在下面的反应代码中,我试图通过更新字典来更改按钮颜色。不幸的是,除非我强制重新渲染,否则它不起作用。
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 undefined
。 https://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 来帮助我们轻松地创建一个新数组。