我使用地图功能从一组对象创建游戏板,并在点击时调用setState以使游戏发生。我可以成功更新状态,但视图不会更新,直到我执行不同的操作。我猜测问题在于map函数如何将props传递给子元素(Cell),但我无法弄清楚我做错了什么。
var board = [];
var width = 50;
var height = 30;
var size = width * height;
for (var i=1; i<=size; i++) {
board[i] = {id: i, status: 'dead'};
}
var Cell = React.createClass({
turn: function() {
this.props.turn(this.props.id);
},
render: function() {
return <div id={this.props.id} className={this.props.status} onClick={this.turn}></div>
}
});
var GameBoard = React.createClass({
getInitialState: function() {
return {
board: board
};
},
handleClick: function(id) {
var newBoard = this.state.board;
newBoard[id] = {id: id, status: 'alive'};
this.setState({board: newBoard});
},
move: function() {
var board = this.state.board;
var newBoard = board;
for (var j=1;j<=board.length;j++) {
if (board[j].status == 'alive') {
newBoard[j-1] = {id: j-1, status: 'alive'};
newBoard[j] = {id: j, status: 'dead'};
}
}
this.setState({board: newBoard});
},
render: function() {
var squares = this.state.board.map(function(item){
return <Cell id={item.id} status={item.status} turn={this.handleClick}/>
}.bind(this));
return (
<div>
<h1>Game of Life</h1>
<button className="btn btn-default" onClick={this.move}>Run</button>
<div className='boardContainer'>{squares}</div>
</div>
);
}
});
ReactDOM.render(<GameBoard/>,document.getElementById('app'));
答案 0 :(得分:0)
move
函数中的循环是逐个循环的,因此在到达setState
的行之前会抛出错误。该方法的前两行只是在变量this.state.board
中指定newBoard
的引用。因此,您正在“更新”您的状态,但未正确使用setState
。这就是为什么电路板会在您的下一次点击时更新,这会在setState
中调用handleClick
。
1)你应该修改状态的深层副本而不是状态本身
2)修复for循环中的off-by-one-error
var board = this.state.board;
var newBoard = board; // Note, this is a reference to this.state.board. That's bad!
for (var j=1; j<=board.length - 1; j++) { // note, -1
...
}
答案 1 :(得分:0)
请使用
if(var i = 0;i < arr.length;i++)
,而不是
if(var i = 1;i<=arr.length;i++){}
在你的问题中,当你的移动函数中的j等于board.length时,它会出错。 在代码中更改两个if循环。 我希望我能提供帮助。
var board = [];
var width = 2;
var height = 3;
var size = width * height;
for (var i=0; i < size; i++) {
board[i] = {id: i, status: 'dead'};
}
var Cell = React.createClass({
turn: function() {
this.props.turn(this.props.id);
},
render: function() {
return <div id={this.props.id} className={this.props.status} onClick={this.turn}></div>
}
});
var GameBoard = React.createClass({
getInitialState: function() {
return {
board: board
};
},
handleClick: function(id) {
var newBoard = this.state.board;
newBoard[id] = {id: id, status: 'alive'};
this.setState({board: newBoard});
},
move: function() {
var board = this.state.board;
var newBoard = board;
for (var j=0;j < board.length;j++) {
if (board[j].status == 'alive') {
newBoard[j-1] = {id: j-1, status: 'alive'};
newBoard[j] = {id: j, status: 'dead'};
}
}
this.setState({board: newBoard});
},
render: function() {
var squares = this.state.board.map(function(item){
return <Cell key = {item.id} fuck={item.id} id={item.id} status={item.status} turn={this.handleClick}/>
}.bind(this));
return (
<div>
<h1>Game of Life</h1>
<button className="btn btn-default" onClick={this.move}>Run</button>
<div className='boardContainer'>{squares}</div>
</div>
);
}
});
ReactDOM.render(<GameBoard/>,document.getElementById('app'));
.dead{
width:10px;height:10px;border:1px solid red;margin:3px;
}
.alive{
border:1px solid green;margin:3px;width:10px;height:10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>
答案 2 :(得分:0)
你正在改变this.state
。 React docs指定这是禁忌。在GameBoard
组件中,我重写了您的handleClick()
和move()
函数,看起来更像是这样:
handleClick: function(id) {
this.setState({
...this.state,
board: [
...this.state.board.slice(0, id),
{
id,
status: 'alive'
},
...this.state.board.slice(id + 1)
]
});
},
move: function() {
this.setState({
...this.state,
board: this.state.board.map((place, id, board) => {
const nextPlace = board[id + 1];
if (nextPlace.status === 'alive') {
return {
...place,
status: 'alive'
};
} else if (place.status === 'alive') {
return {
...place,
status: 'dead'
};
}
return place;
})
});
},
注意:这些函数使用一些新的Javascript功能,如spread运算符(...place
)和箭头函数。当您尝试运行此代码时,这些功能可能会导致语法错误。