javascript - 为什么 setState() 不更新 React 上的渲染?
问题描述
我正在尝试制作一个由“Cells”组成的 2D 游戏板,该游戏板具有称为isAlive
. 用户可以通过单击它们来更改此值。该值使用不同的颜色指示给用户。Board.js
构造函数创建具有false
值的每个单元格。该板还有一个“重置”按钮,可将所有 Cell 重置为false
.
当我单击它们时,单元格的值会正确更改。单击“重置”按钮时,我希望每个单元格的isAlive
值为false
. 然而,当视觉上按下“重置”按钮时,板上没有变化(单元格的颜色没有变化)。打印所有单元格的console.log(this.state.cells);
在线 handleClick()
方法。那么为什么 Cell 没有在视觉上更新呢?我在这里做错了什么?Board.js
props: Object { isAlive: false }
Board.js
export default class Board extends React.Component {
constructor(props) {
super(props);
this.state = {
cells: []
};
this.rowNum = 10;
this.colNum = 10;
for (let i = 0; i < (this.rowNum * this.colNum); i++) {
this.state.cells.push(<Cell isAlive={false}/>);
}
this.handleClick = this.handleClick.bind(this);
this.getCols = this.getCols.bind(this);
}
getCols() {
let cols = [];
for (let i = this.rowNum; i <= (this.rowNum * this.colNum); i += this.rowNum) {
cols.push(this.state.cells.slice(i - this.rowNum, i).map(function (item, i) {
return <div key={i}>{item}</div>
}));
}
return cols;
}
handleClick() {
const newBoard = this.state.cells;
newBoard.forEach((item, index, arr) => {
arr[index] = <Cell isAlive={false}/>
});
this.setState({
cells: newBoard
}, function () {
console.log(this.state.cells);
}
);
}
render() {
return (<div className="background">
<table className="gameBoard">
<tbody>
<tr>
{this.getCols().map(function (item, index) {
return <td className="col" key={index}>{item}</td>
})}
</tr>
</tbody>
</table>
<button onClick={this.handleClick}> Reset</button>
</div>
);
}
}
Cell.js 的重要部分:
export default class Cell extends React.Component {
constructor(props) {
super(props);
this.colors = {
dead: '#041b40',
alive: '#b2e8f7',
hover_dead: '#495d76',
hover_alive: '#e6fffd'
};
this.state = {
isAlive: this.props.isAlive,
isMouseDown: false,
isHovering: false
};
this.handleClick = this.handleClick.bind(this)
}
handleClick() {
this.setState({
isAlive: !this.state.isAlive,
isMouseDown: this.state.isMouseDown,
isHovering: this.state.isHovering
})
}
...
determineColor() {
if (this.state.isAlive && this.state.isHovering) {
return this.colors.hover_alive;
} else if (!this.state.isAlive && this.state.isHovering) {
return this.colors.hover_dead;
} else if (this.state.isAlive && !this.state.isHovering) {
return this.colors.alive;
}else {
return this.colors.dead;
}
}
render() {
return (
<div>
<button className='square'
onClick={this.handleClick}
type='button'
style={{
backgroundColor: this.determineColor()
}}>
</button>
</div>
)
};
}
解决方案
您需要更新道具更改的内部状态:
export default class Cell extends React.Component {
constructor(props) {
super(props);
this.colors = {
dead: '#041b40',
alive: '#b2e8f7',
hover_dead: '#495d76',
hover_alive: '#e6fffd'
};
this.state = {
isAlive: this.props.isAlive,
isMouseDown: false,
isHovering: false
};
this.handleClick = this.handleClick.bind(this)
}
componentDidUpdate(prevProps, prevState) { //<--HERE
this.setState({isAlive: this.props.isAlive})
}
handleClick() {
this.setState({
isAlive: !this.state.isAlive,
isMouseDown: this.state.isMouseDown,
isHovering: this.state.isHovering
})
}
...
determineColor() {
if (this.state.isAlive && this.state.isHovering) {
return this.colors.hover_alive;
} else if (!this.state.isAlive && this.state.isHovering) {
return this.colors.hover_dead;
} else if (this.state.isAlive && !this.state.isHovering) {
return this.colors.alive;
}else {
return this.colors.dead;
}
}
render() {
return (
<div>
<button className='square'
onClick={this.handleClick}
type='button'
style={{
backgroundColor: this.determineColor()
}}>
</button>
</div>
)
};
推荐阅读
- java - 使用 iText 将 tiff 转换为 pdf 时,字节数组不是图像格式错误
- vba - VBA Word 将现有形状添加到主标题
- reactjs - 在 React 中动态调用方法
- firebase - 如何使用 PubSub 一次获取一条消息
- macos - 在 Mac 上安装 Tensorflow 的问题
- javascript - forEach() 中的 parseFloat() 不起作用
- ios - 使导航控制器的 largeTitleDisplayMode 对特定的滚动视图做出反应
- python - 从 Pandas 数据框生成三元组
- php - 如何防止意外的语法错误?
- android - React Native 应用程序无法在真正的 Android 手机上运行