Redux/Redux Saga实战:如何等待Store更新实现循环玩家回合?
问题背景
我正在用React结合Redux与Redux Saga开发一款卡牌游戏模拟器,需要实现这样一个逻辑:更新Redux状态后,等待新状态生成并再次执行回合流程。我不确定在React Redux体系里该怎么实现这个逻辑,下面是我的简化需求代码:
function endTurn() { // do something } function playerTurn(playerHand) { const decision = getPlayerDecision(playerHand); updatePlayerHand(decision); // 此方法分发action以更新Redux状态 // 若玩家选择'Stand',游戏结束;否则继续玩家回合 if(decision === 'Stand') { endTurn(); } else { // 此处需要获取更新后的手牌,该如何实现? playerTurn(updatedHand); } }
一开始我想把逻辑放在componentWillReceiveProps里,但感觉这个方案很不合理,还容易产生Bug。直觉告诉我Redux Saga是解决这个问题的合适工具,但翻了文档没找到相关的实现思路,想求个解决方案。
解决方案
后来参考了Krasimir提到的yield select用法,终于找到了方向,下面是最终实现的简化代码:
import { put, takeEvery, select } from 'redux-saga/effects'; function* playPlayerTurn() { const playerHand = yield select(getPlayerHand); const decision = getPlayerDecision(playerHand); // 执行决策的action,会改变playerHand yield put({ type: `PLAY_PLAYER_DECISION`, decision, }); // 若玩家选择'Stand',回合结束;否则继续玩家回合 if(decision === 'Stand') { console.log('PLAYER OVER'); } else { console.log('PLAYER AGAIN'); yield put({ type: `PLAY_PLAYER_TURN`, }); } } export function* playerTurnWatcher() { yield takeEvery(`PLAY_PLAYER_TURN`, playPlayerTurn); }
核心思路其实是通过递归调用saga来实现需求:每次触发PLAY_PLAYER_TURN时,先用select获取Redux里最新的玩家手牌,然后执行决策对应的action更新状态;如果玩家没选择结束,就再次触发PLAY_PLAYER_TURN,让流程循环下去,这样每次都能拿到更新后的状态。
内容的提问来源于stack exchange,提问作者user2634633
相关产品推荐
相关产品推荐

