在 React JS 的 this.setState 的回调中使用 this.setState?
Posted
技术标签:
【中文标题】在 React JS 的 this.setState 的回调中使用 this.setState?【英文标题】:Using this.setState in the callback of this.setState in React JS? 【发布时间】:2017-05-23 12:18:39 【问题描述】:是否可以在this.setState的回调中调用this.setState?
我正在制作一个 Roguelike Dungeon 并且有一个设置,在 this.setState 的回调中使用了一个辅助函数,它再次调用 this.setState。我的游戏此时卡住了。
所以我在 React 组件中有一个对象,它具有生成随机二维数组映射的方法:
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)时它可以工作,但第二次它冻结了。谁能帮帮我?
【问题讨论】:
是的,您可以在另一个setState()
的回调中调用setState()
。冻结很可能与回调本身无关。
【参考方案1】:
我会看看你在状态中设置 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() 可能 替换您所做的突变。把 this.state 当作是 不可变。
当您将 map 属性传递给 setstate 时,它将保留对 this.Dungeon.map 的引用,如果您随后对其进行修改将导致问题。您应该复制 .map 的内容并将其传递给 state。
您还应该让一个组件负责状态,而不是在不同的函数中多次调用它。来自react docs
setState() 不会立即改变 this.state 而是创建一个 等待状态转换。调用 this 后访问 this.state 方法可能会返回现有值。
不保证 setState 调用的同步操作 并且调用可能会被批处理以提高性能。
由于所有多个 setstate 调用,您的冻结可能来自渲染方法中的竞争条件。
【讨论】:
【参考方案2】:就像弗兰克的代码一样,我有这个:
this.setState( state =>
state.board = this.Dungeon.map
return state
)
我希望它对你有用,或者我做错了,或者误解了你的问题
【讨论】:
这会改变旧状态,它是 React 中未定义的行为(反模式,不鼓励)。以上是关于在 React JS 的 this.setState 的回调中使用 this.setState?的主要内容,如果未能解决你的问题,请参考以下文章
React 、React.js、React Native三者关系
React.js Chrome 扩展 - 如何将 Background.js 中的数据存储在 React 内部的变量中?