通常,在遇到重击时,您会调用其他动作:
const startRecipe = {type: "startRecipe"}
const reducer = (state, action) => {
if (action.type === "startRecipe") {
state.mode = AppMode.CookRecipe
}
}
const getRecipeFromUrl = () => async dispatch => {
const res = await Parser.getRecipeFromUrl(url)
dispatch(startRecipe)
}
在redux工具包中使用createAsyncThunk
,这并不是那么简单。的确,您可以在extraReducers
中更改操作产生的状态:
export const getRecipeFromUrl = createAsyncThunk('getRecipeFromUrl',
async (url: string): Promise<RecipeJSON> => await Parser.getRecipeFromUrl(url)
)
const appStateSlice = createSlice({
name: 'app',
initialState: initialAppState,
reducers: {},
extraReducers: ({ addCase }) => {
addCase(getRecipeFromUrl.fulfilled, (state) => {
state.mode = AppMode.CookRecipe
})
}
})
但是我也想通过非异步方式来启动配方,这将需要在切片中使用化简器:
reducers: {
startRecipe(state): state.mode = AppState.CookRecipe
},
为了避免在两个地方编写相同的代码,我希望能够从thunk处理程序中调用简单的reducer函数。我只是从startRecipe(state)
的情况中尝试过startRecipe
和extraReducers
(已经针对鸭子的输出进行了重组,所以我敢肯定我指的是正确的函数),但是没有用。
我当前的解决方案是在切片之外定义_startRecipe
并在两种情况下都引用该函数
reducers: { startRecipe: _startRecipe },
extraReducers: builder => {
builder.addCase(getRecipeFromUrl.fulfilled, _startRecipe)
}
有没有一种“更好”的方式,您可以在slice.reducers
中定义简单操作,并从extraReducers
中的thunk处理程序中引用它?
答案 0 :(得分:1)
从概念上讲,“调用减速器”的想法是错误的方法。 Redux的部分设计在于,触发状态更新的 only 方法是通过分派动作。
如果您使用switch
语句编写reducer,则可能有多种操作类型,因为它们都是由同一块处理的:
switch(action.type) {
case TypeA:
case TypeB: {
// common logic for A and B
}
case C: // logic for C
}
使用createSlice
时,您可以通过在对createSlice
的调用之外定义一个“ case reducer”函数来模仿此模式,并针对每种要处理的案例传递它:
const caseReducerAB = (state) => {
// update logic here
}
const slice = createSlice({
name: "mySlice",
initialState,
reducers: {
typeA: caseReducerAB,
typeB: caseReducerAB,
}
extraReducers: builder => {
builder.addCase(someAction, caseReducerAB)
}
})
这听起来像您所说的“当前解决方案”,是的,这就是我的建议。
答案 1 :(得分:0)
payloadCreator
的第二个参数是thunkAPI
(doc),您可以在其中调度cookRecipe
动作。
export const getRecipeFromUrl = createAsyncThunk('getRecipeFromUrl',
async (url: string, thunkAPI: ThunkApiConfig): Promise<RecipeJSON> => {
await Parser.getRecipeFromUrl(url)
return thunkAPI.dispatch(cookRecipeActionCreator())
}
)