组件传递给worker Saga的action.payload处理中变为undefined求助
问题:Action Payload传递到Worker Saga后变为Undefined
我遇到一个问题:从组件把action.payload传递到Worker Saga后,在处理Action的过程中它变成了undefined。控制台打印显示action.payload.queries和action.payload.chosenQueryId均为undefined。以下是我的代码片段:
组件中的Action触发代码
const showQueryOnMapHandler = (event) => { const chosenQueryId = +event.currentTarget.id; dispatch(mapActions.setCoordinates({ chosenQueryId, queries })); };
Saga代码
const getQueryCoordinates = (action) => { console.log(action.payload.queries); console.log(action.payload.chosenQueryId); const queryIndex = action.payload.queries.findIndex( (element) => element.queryId === action.payload.chosenQueryId ); const coordinatesFromTo = { newFromLat: action.payload.queries[queryIndex].coordinatesFrom.lat, newFromLng: action.payload.queries[queryIndex].coordinatesFrom.lng, newToLat: action.payload.queries[queryIndex].coordinatesTo.lat, newToLng: action.payload.queries[queryIndex].coordinatesTo.lng, }; return coordinatesFromTo; }; function* workerQueryClickSaga(action) { yield put(queriesActions.choseQuery(action.payload.chosenQueryId)); yield put(mapActions.setCoordinates(getQueryCoordinates(action))); yield put(mapActions.setBounds()); } function* watchQueryClickSaga() { yield takeEvery("map/setCoordinates", workerQueryClickSaga); } function* rootSaga() { yield fork(watchQueryClickSaga); } export default rootSaga;
Redux Store配置
import { configureStore } from "@reduxjs/toolkit"; import createSagaMiddleware from "redux-saga"; import mapSlice from "./reducers/map-slice"; import queriesSlice from "./reducers/queries-slice"; import rootSaga from "./sagas"; const saga = createSagaMiddleware(); const store = configureStore({ reducer: { queries: queriesSlice.reducer, map: mapSlice.reducer }, middleware: [saga], }); saga.run(rootSaga); export default store;
Map Slice代码
import { createSlice } from "@reduxjs/toolkit"; const mapSlice = createSlice({ name: "map", initialState: { fromLat: null, fromLng: null, toLat: null, toLng: null, bounds: null, fetchedPolyline: [], }, reducers: { setCoordinates(state, action) { state.fromLat = action.payload.fromLat; state.fromLng = action.payload.fromLng; state.toLat = action.payload.toLat; state.toLng = action.payload.toLng; }, setBounds(state) { state.bounds = [ [state.fromLat, state.fromLng], [state.toLat, state.toLng], ]; }, }, }); export const mapActions = mapSlice.actions; export default mapSlice;
Queries Slice代码(存在笔误)
import { createSlice } from "@reduxjs/toolkit"; const mapSlice = createSlice({ name: "map", initialState: { fromLat: null, fromLng: null, toLat: null, toLng: null, bounds: null, fetchedPolyline: [], }, reducers: { setCoordinates(state, action) { state.fromLat = action.payload.fromLat; state.fromLng = action.payload.fromLng; state.toLat = action.payload.toLat; state.toLng = action.payload.toLng; }, setBounds(state) { state.bounds = [ [state.fromLat, state.fromLng], [state.toLat, state.toLng], ]; }, }, }); export const mapActions = mapSlice.actions; export default mapSlice;
已尝试的方法
我试过把getQueryCoordinates函数的逻辑直接放到workerQueryClickSaga里,但问题依然存在。
问题原因与修复方案
核心问题
- 循环触发Action导致Payload丢失:你的Saga监听了
map/setCoordinates这个Action,但在workerQueryClickSaga里又再次调用put(mapActions.setCoordinates(...)),形成循环触发。第二次触发时,传递的payload是getQueryCoordinates(action)返回的对象(只有newFromLat等坐标字段),没有queries和chosenQueryId,所以后续Saga处理时action.payload自然找不到这些属性,打印为undefined。 - Queries Slice笔误:你提供的Queries Slice代码完全复制了Map Slice的内容,这会导致Redux状态管理混乱,也无法正常使用
queriesActions.choseQuery。
修复步骤
- 新增专用触发Action:在Queries Slice里创建专门用于触发查询点击的Action,而非复用Map的Action:
// queries-slice.js 修正后代码 import { createSlice } from "@reduxjs/toolkit"; const queriesSlice = createSlice({ name: "queries", initialState: { chosenQueryId: null, queryList: [] // 根据实际需求定义状态 }, reducers: { choseQuery(state, action) { state.chosenQueryId = action.payload; }, // 新增专门触发Saga的Action queryClicked(state, action) { // 此Action仅作为Saga触发信号,无需修改状态 } }, }); export const queriesActions = queriesSlice.actions; export default queriesSlice;
- 组件中触发正确的Action:
const showQueryOnMapHandler = (event) => { const chosenQueryId = +event.currentTarget.id; // 触发新增的queryClicked,传递所需参数 dispatch(queriesActions.queryClicked({ chosenQueryId, queries })); };
- 修改Saga监听与逻辑:
function* workerQueryClickSaga(action) { const { chosenQueryId, queries } = action.payload; yield put(queriesActions.choseQuery(chosenQueryId)); // 直接从payload取数据,避免依赖循环触发的Action const queryIndex = queries.findIndex(element => element.queryId === chosenQueryId); const coordinates = { fromLat: queries[queryIndex].coordinatesFrom.lat, fromLng: queries[queryIndex].coordinatesFrom.lng, toLat: queries[queryIndex].coordinatesTo.lat, toLng: queries[queryIndex].coordinatesTo.lng, }; yield put(mapActions.setCoordinates(coordinates)); yield put(mapActions.setBounds()); } function* watchQueryClickSaga() { // 监听新增的queries/queryClicked Action yield takeEvery("queries/queryClicked", workerQueryClickSaga); }
这样就能彻底避免循环触发的问题,保证Saga每次都能拿到完整且正确的payload。
内容的提问来源于stack exchange,提问作者AlexCap
相关产品推荐
相关产品推荐

