Redux Saga执行put操作后,如何重新获取更新后的state?
嘿,我来帮你梳理下这个问题的原因和解决办法~
你点击按钮后第二个console.log输出0而不是期望的10,核心问题出在Redux-Saga的执行时机和状态获取的逻辑上。
为什么会出现这个情况?
Redux-Saga里的put操作是非阻塞的——当你在set_number_async里执行yield put(action_creators.get_action_of_set_number_async2(...))时,只是把这个action派发给了store,你的saga会立刻继续执行后面的yield select,而不会等待set_number_async2对应的saga逻辑跑完,也不会等reducer完成状态更新。
也就是说,你在put之后马上select的时候,set_number_async2里的put(set_number)还没触发reducer更新状态,所以拿到的还是原来的0。
两种可行的解决方案
方案1:等待目标action触发后再获取状态
在set_number_async里,派发出set_number_async2之后,用take方法等待set_number这个action被触发(这意味着reducer已经完成了状态更新),之后再去select新状态:
function* set_number_async(action: Action<{ number:number }>) { let state = yield select((state) => state.number); console.log('first', state); // 0 yield delay(1000); yield put(action_creators.get_action_of_set_number_async2(action.payload!)); // 等待set_number action执行完成,确保状态已更新 yield take('set_number'); state = yield select((state) => state.number); console.log('second', state); // 现在会输出10 }
方案2:合并冗余的saga逻辑
看你的代码,set_number_async2只是简单地把action转发给set_number,完全可以把这部分逻辑合并到set_number_async里,这样就能确保状态更新后再获取:
function* set_number_async(action: Action<{ number:number }>) { let state = yield select((state) => state.number); console.log('first', state); // 0 yield delay(1000); // 直接派发set_number action,跳过中间的async2 yield put(action_creators.get_action_of_set_number(action.payload!)); // 此时reducer已经同步完成状态更新,select能拿到最新值 state = yield select((state) => state.number); console.log('second', state); // 输出10 } // 同时记得更新saga监听,移除set_number_async2的监听 export function* saga() { yield all([ takeEvery('set_number_async', set_number_async), // 删掉这一行:takeEvery('set_number_async2', set_number_async2) ]); }
额外的语法错误修复
另外注意你的map_state_to_props里有个语法小错误,分号应该改成逗号(或者去掉):
// 错误写法 function map_state_to_props(state) { return { number: state.number; } } // 正确写法 function map_state_to_props(state) { return { number: state.number }; }
这个错误可能会导致组件无法正确获取状态,先把它修复哦~
内容的提问来源于stack exchange,提问作者left click

