0

通常在一个 thunk 中,您最终会调用其他操作:

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)
}

createAsyncThunkredux 工具包中,这并不是那么简单。实际上,您可以从结果中的操作中改变状态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并从 thunk 处理程序中引用它extraReducers

4

2 回答 2

5

的第二个参数payloadCreatorthunkAPIdoc),您可以从哪里分派cookRecipe操作。

export const getRecipeFromUrl = createAsyncThunk('getRecipeFromUrl',
  async (url: string, thunkAPI: ThunkApiConfig): Promise<RecipeJSON> => {
    await Parser.getRecipeFromUrl(url)
    return thunkAPI.dispatch(cookRecipeActionCreator())
  }
)
于 2020-10-14T12:20:37.450 回答
1

从概念上讲,“调用减速器”的想法是错误的方法。Redux 的部分设计是触发状态更新的唯一方法是调度一个动作。

如果您使用switch语句编写 reducer,您可以有多个动作类型作为案例,所有这些都由同一个块处理:

switch(action.type) {
  case TypeA:
  case TypeB: {
    // common logic for A and B
  }
  case C: // logic for C
}

使用 时createSlice,您可以通过在调用之外定义“case reducer”函数来模仿这种模式createSlice,并将它传递给您要处理的每个案例:

const caseReducerAB = (state) => {
  // update logic here
}

const slice = createSlice({
  name: "mySlice",
  initialState,
  reducers: {
    typeA: caseReducerAB,
    typeB: caseReducerAB,
  }
  extraReducers: builder => {
    builder.addCase(someAction, caseReducerAB)
  }
})

这听起来像您所说的“当前解决方案”,所以是的,这就是我的建议。

于 2020-05-11T16:13:40.697 回答