Redux Saga Selector无法获取状态值及getState报错求助
让我们一步步拆解你遇到的问题,然后逐个解决:
核心错误点梳理
1. 直接在模块顶层调用getState()导致报错
getState是Redux Store实例的专属方法,不是全局变量,只能在特定上下文(比如Saga的select effect、Thunk的getState参数)中使用。你尝试在模块顶层写getState().ASVersionQueueState.versionQueueFilter,相当于调用一个不存在的全局函数,必然触发Cannot find the name getState错误。
2. Action Creator错误传递Selector函数而非状态值
你的pollVersions action creator里,把Selector函数getVersionQueueFilters直接赋值给了versionQueueFilter字段,而不是当前的过滤值:
pollVersions: () => { return { type: 'POLL_VERSIONS', versionQueueFilter: getVersionQueueFilters, versionQueueRefresh: true } },
这会导致后续reducer中action.versionQueueFilter === state.versionQueueFilter永远为false(函数和对象引用无法相等),请求成功后根本不会更新状态。而且Saga的Action Creator应该是纯函数,不能直接依赖Store状态,状态获取逻辑应该放在Saga中处理。
3. Selector函数接收的参数类型错误
你的Selector期望接收ASVersionQueueState类型的参数,但Redux的select effect会把整个根Redux状态传给Selector。如果根状态中你的reducer对应的key是asVersionQueue(假设合并时用的这个key),Selector就无法正确定位到目标slice,自然返回不了正确的过滤值。
分步修复方案
步骤1:修正Selector函数
首先定义根状态类型(根据你实际合并reducers的key调整),然后让Selector接收根状态并定位到目标slice:
// 定义根状态类型,包含所有reducer对应的slice export interface RootState { asVersionQueue: ASVersionQueueState; // 其他reducer的slice... } // 修正后的Selector:从根状态中取出目标slice,再获取过滤值 export const getVersionQueueFilters = (state: RootState) => state.asVersionQueue.versionQueueFilter;
步骤2:修正Action Creator
让pollVersions成为无参数的纯Action,不再传递过滤值(过滤值由Saga自己获取):
export const actionCreators = { pollVersions: () => { return { type: 'POLL_VERSIONS', versionQueueRefresh: true } as const; }, // 其他Action Creator保持不变,但更新类型定义 pollRequestVersions: (versionQueueFilter: VersionQueueFilter, versionQueueRefresh: boolean) => { return { type: 'POLL_REQUEST_VERSIONS', versionQueueFilter, versionQueueRefresh } as const; }, pollRequestVersionsSuccess: (versionQueueFilter: VersionQueueFilter, versionQueueRefresh: boolean, data: QueuedVersion[]) => { return { type: 'POLL_REQUEST_VERSIONS_SUCCESS', versionQueueFilter, receivedVersions: data, versionQueueRefresh } as const; }, pollRequestVersionsError: () => { return { type: 'POLL_REQUEST_VERSIONS_ERROR' } as const; } }; // 同步更新Action类型定义,去掉PollVersionsAction中的versionQueueFilter字段 interface PollVersionsAction { type: 'POLL_VERSIONS'; versionQueueRefresh: boolean; }
步骤3:修正Saga逻辑
在fetchPollVersionsAsync中通过select获取当前过滤值,替代从Action中接收:
export function* fetchPollVersionsAsync(action: PollVersionsAction) { try { // 通过select获取当前最新的过滤值 const versionQueueFilters = yield select(getVersionQueueFilters); yield put(actionCreators.pollRequestVersions(versionQueueFilters, action.versionQueueRefresh)); const data = yield call(() => { return fetch('api/Versions') .then(res => res.json()) as Promise<QueuedVersion[]>; }); yield put(actionCreators.pollRequestVersionsSuccess(versionQueueFilters, action.versionQueueRefresh, data)); } catch (error) { yield put(actionCreators.pollRequestVersionsError()); } }
步骤4:修复Reducer中的比较逻辑
因为对象是引用类型,直接比较action.versionQueueFilter === state.versionQueueFilter可能因为不可变更新导致引用不同,建议比较关键属性或使用深比较:
case 'POLL_REQUEST_VERSIONS_SUCCESS': // 比较过滤值的关键属性,判断是否为最新请求 const isSameFilter = action.versionQueueFilter.StartDate === state.versionQueueFilter.StartDate && action.versionQueueFilter.EndDate === state.versionQueueFilter.EndDate && JSON.stringify(action.versionQueueFilter.PieceType) === JSON.stringify(state.versionQueueFilter.PieceType) && JSON.stringify(action.versionQueueFilter.EventType) === JSON.stringify(state.versionQueueFilter.EventType) && action.versionQueueFilter.EventID === state.versionQueueFilter.EventID && action.versionQueueFilter.Employee === state.versionQueueFilter.Employee; if (isSameFilter && action.versionQueueRefresh === state.versionQueueRefresh) { return { ...state, queuedVersions: action.receivedVersions, versionQueueRefresh: action.versionQueueRefresh, gridIsLoading: false }; } break;
步骤5:确保轮询Saga被注册
别忘了把watchVersionPoller加入到sagas数组中,否则轮询逻辑不会生效:
export const sagas = [ takeEvery('POLL_VERSIONS', fetchPollVersionsAsync), watchVersionPoller // 注册轮询监听Saga ];
这些修改完成后,你的Selector就能正确获取状态值,getState的错误会消失,轮询时也能传递当前最新的过滤值了。
内容的提问来源于stack exchange,提问作者CHY

