是否可以在this.setState的回调中调用this.setState?
我正在创建一个Roguelike Dungeon并且有一个设置,在this.setState的回调中使用了一个辅助函数,它再次调用this.setState。我的游戏此时冻结了。
所以我在React组件中有一个对象,它有一个生成随机2D数组映射的方法:
this.Dungeon.Generate();
当游戏开始时,我们在componentDidMount()中调用组件中的以下函数:
componentDidMount: function() {
this.Dungeon.Generate();
this.setState({
board: this.Dungeon.map
}, function() {
this.generateGamePlay();
});
},
this.generateGamePlay()看起来像这样,基本上生成并将玩家,老板和物品随机放在棋盘上:
generateGamePlay: function() {
var board = this.state.board.slice();
var startPosition = this.randomPosition();
board[startPosition[0]][startPosition[1]] = this.state.player;
var bossPosition = this.randomPosition();
board[bossPosition[0]][bossPosition[1]] = this.state.boss[this.state.dungeonLevel];
this.generateWeapons(this.state.dungeonLevel,board);
this.generateFood(this.state.dungeonLevel, board);
this.generateEnemies(this.state.dungeonLevel, board);
this.setState({
board: board
});
},
但是当玩家死亡时,我们再次呼叫以重置游戏:
this.Dungeon.Generate();
//generate a new dungeon map, available in this.Dungeon.map
this.setState({
board: this.Dungeon.map, currentMessage: "Game restarted", player: player, weapon: weapon, dungeonLevel: 0
}, function(){
this.generateGamePlay();
})
但是当我的游戏冻结时。所以我第一次调用this.generateGamePlay()(调用this.setState)它可以工作,但第二次冻结。有人可以帮帮我吗?
答案 0 :(得分:2)
我会看看你正在设置this.Dungeon.map状态的部分。
this.setState({
board: this.Dungeon.map, currentMessage: "Game restarted", player: player, weapon: weapon, dungeonLevel: 0
}, function(){
this.generateGamePlay();
})
我的猜测是其他东西可能正在改变地图对象而不使用setstate,因为它是Dungeon的属性。
来自react docs 的
不要直接改变this.state,因为之后调用setState()可能 替换你所做的突变。把它当作状态对待 不可变的。
当你将map属性传递给setstate时,它将保留对this.Dungeon.map的引用,如果你随后修改将导致问题。你应该复制.map的副本并将其传递给state。
您还应该制作一个负责状态的组件,而不是在不同的功能中多次调用它。来自react docs
setState()不会立即改变this.state但会创建一个 待定状态转换。调用后访问this.state 方法可以返回现有值。
无法保证对setState的调用同步操作 并且可以批量调用以获得性能提升。
由于所有多个setstate调用,你的冻结可能来自渲染方法中的竞争条件。
答案 1 :(得分:0)
就像弗兰克的代码一样,我有这样的代码:
this.setState( state => {
state.board = this.Dungeon.map
return state
})
我希望这对您很方便,或者我做错了,或者误解了您的问题