从createAsyncThunk

时间:2020-05-11 00:15:53

标签: redux redux-toolkit

通常,在遇到重击时,您会调用其他动作:

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)的情况中尝试过startRecipeextraReducers(已经针对鸭子的输出进行了重组,所以我敢肯定我指的是正确的函数),但是没有用。

我当前的解决方案是在切片之外定义_startRecipe并在两种情况下都引用该函数

  reducers: { startRecipe: _startRecipe },
  extraReducers: builder => {
    builder.addCase(getRecipeFromUrl.fulfilled, _startRecipe)
  }

有没有一种“更好”的方式,您可以在slice.reducers中定义简单操作,并从extraReducers中的thunk处理程序中引用它?

2 个答案:

答案 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的第二个参数是thunkAPIdoc),您可以在其中调度cookRecipe动作。

export const getRecipeFromUrl = createAsyncThunk('getRecipeFromUrl',
  async (url: string, thunkAPI: ThunkApiConfig): Promise<RecipeJSON> => {
    await Parser.getRecipeFromUrl(url)
    return thunkAPI.dispatch(cookRecipeActionCreator())
  }
)