如何在Redux Toolkit中存储搜索条件参数及解决pending阶段取值问题
问题
我正在基于搜索条件获取行程(Journey)数据,希望将这些搜索条件(SearchCriteria)存储到Redux Store中。尝试在extraReducer的pending阶段访问action.payload但无法成功,请问该如何将搜索条件参数存入Store?
附现有代码:
import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit' import axios from "axios" import { Journey, SearchCriteria } from '../types' import constants from "../constants"; type InitialState = { loading: boolean journeys: Journey[] criteria: SearchCriteria | null error: string } const initialState: InitialState = { loading: false, journeys: [], criteria: null, error: '', }; // generates pending, fulfilled and rejected action types export const fetchJourneys = createAsyncThunk("user/fetchUsers", async (criteria: SearchCriteria) => { const response = await axios.get(`${constants.api_server}/journeys?from=${criteria.from}&to=${criteria.to}&departure=${criteria.departure}`); return response.data.journeys; }); const journeySlice = createSlice({ name: "journey", initialState, reducers: {}, extraReducers: builder => { builder.addCase(fetchJourneys.pending, (state, action) => { console.log(action) state.loading = true }) builder.addCase(fetchJourneys.fulfilled, (state, action: PayloadAction<Journey[]>) => { state.loading = false state.journeys = action.payload state.error = '' }) builder.addCase(fetchJourneys.rejected, (state, action) => { state.loading = false, state.journeys = [], state.error = action.error.message || 'Someting went wrong' }) } }); export default journeySlice.reducer
解决方案
核心原因
你在pending阶段拿不到action.payload是因为:createAsyncThunk生成的pending action中,你传入的搜索条件参数并不在payload字段里,而是存放在action.meta.arg中。payload字段只会在fulfilled阶段被赋值为异步请求的返回结果。
修改代码实现
你只需要在pending或者fulfilled阶段,把action.meta.arg赋值给state.criteria即可。另外注意你的createAsyncThunk类型名写错了(写成了user/fetchUsers,应该对应slice的name改成journey/fetchJourneys),以下是修正后的完整代码:
import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit' import axios from "axios" import { Journey, SearchCriteria } from '../types' import constants from "../constants"; type InitialState = { loading: boolean journeys: Journey[] criteria: SearchCriteria | null error: string } const initialState: InitialState = { loading: false, journeys: [], criteria: null, error: '', }; // 修正异步action的类型名,对应slice的name export const fetchJourneys = createAsyncThunk("journey/fetchJourneys", async (criteria: SearchCriteria) => { const response = await axios.get(`${constants.api_server}/journeys?from=${criteria.from}&to=${criteria.to}&departure=${criteria.departure}`); return response.data.journeys; }); const journeySlice = createSlice({ name: "journey", initialState, reducers: {}, extraReducers: builder => { builder.addCase(fetchJourneys.pending, (state, action) => { state.loading = true // 从meta.arg中获取搜索条件并存入state state.criteria = action.meta.arg }) builder.addCase(fetchJourneys.fulfilled, (state, action: PayloadAction<Journey[]>) => { state.loading = false state.journeys = action.payload state.error = '' // 如果你希望请求成功后再存条件,也可以把赋值写在这里 // state.criteria = action.meta.arg }) builder.addCase(fetchJourneys.rejected, (state, action) => { state.loading = false state.journeys = [] state.error = action.error.message || 'Something went wrong' }) } }); export default journeySlice.reducer
补充说明
- 如果希望发起请求时立即更新搜索条件,就在pending阶段赋值;如果希望请求成功后再更新,就在fulfilled阶段赋值。
- 你原代码中
createAsyncThunk的第一个参数(action类型前缀)写成了user/fetchUsers,和slice的name: "journey"不匹配,建议修正为journey/fetchJourneys,方便调试时识别action来源。
内容的提问来源于stack exchange,提问作者Alex Aung
相关产品推荐
相关产品推荐

