如何在Redux Toolkit createSlice函数中重用reducer逻辑?

时间:2020-07-19 07:25:44

标签: reactjs redux react-redux redux-toolkit

我是React的新手,正在学习使用React来构建Web应用程序。我发现Redux Toolkit很有用,并使用其4×4 DataFrame │ Row │ x1 │ x2 │ x3 │ x4 │ │ │ Float64 │ Float64 │ Float64 │ Float64 │ ├─────┼──────────┼───────────┼──────────┼───────────┤ │ 1 │ 0.236197 │ 0.509669 │ 0.353128 │ 0.615519 │ │ 2 │ 10.0 │ 12.0 │ 14.0 │ 16.0 │ │ 3 │ 0.976431 │ 0.771457 │ 0.282455 │ 0.979453 │ │ 4 │ 0.445266 │ 0.0327924 │ 0.450912 │ 0.0135655 │ 函数来实现基本功能。但是,我遇到了与“最佳做法”相关的问题,不确定我是否正确构建了应用程序的体系结构。

假设我在Redux中存储了一个createSlice()对象。我创建了一个异步thunk函数来获取相关信息:

user

相应地,我按如下方式处理了export const getUserInfo = createAsyncThunk('user/get', async (userId, thunkApi) => { // fetching information using api } 回调:

pending/fulfilled/rejected

考虑到修改显示状态标志在其他功能api实现中非常普遍,我在const userSlice = createSlice({
 name: 'user',
 initialState,
 reducers: { 
 setShowProgress(state, action: PayloadAction<boolean>) { 
 state.showProgress = action.payload;
 },
 clearError(state) {
 state.error = null; 
 state.errorMessage = null; 
 } }, extraReducers: builder => { builder.addCase(getUserInfo.pending, (state, action) => { // My question is here >_< } builder.addCase(getUserInfo.fulfilled, (state, action) => { // handle data assignments }) builder.addCase(getUserInfo.rejected, (state, action) => { // handle error messages }) } }) 中包装了两个函数(setShowProgress()clearError())。我的问题来了:如何在reducers函数中引用这两个函数?

尽管我可以只在getUserInfo.pending中分配showProgresserror状态变量,而不必尝试调用reducer函数,但是当我在其中实现其他提取操作时,肯定会引入重复的代码未来。如果不是推荐的模式,那么此方案的最佳实践是什么?

2 个答案:

答案 0 :(得分:2)

如果您的目标只是基于loading / error / pending设置fulfilled布尔值或rejected属性,则可以只使用{{ 1}}是在1.4版中引入的。

这是一个使用通用帮助程序在许多片中简化操作的非常基本的示例。

addMatcher

答案 1 :(得分:0)

使用redux-toolkit中的createReducer将旧的开关盒方法替换为新的开关盒方法时,我遇到了类似的问题。

在旧方法中,我经常为许多动作使用通用的reducer,如下所示:

this.service.selectedProfile.pipe(
  takeUntil(this.unsubscribe$)
).subscribe((selectedProfile: any) => {
  this.selectedProfile = selectedProfile;

  /* Update beneficiaries and categories lists now 
  that the selectedProfile has changed.*/  
  this.updateBeneficiariesListAndCategories(selectedProfile).subscribe((res) => {
    // Do whatever you need with returned data
  });
});


/**
 * Place parallel requests to update beneficiaries and categoies
 * for a specific profile and update caches
 */
updateBeneficiariesListAndCategories(profile: any): Observable < any > {

  // Clear beneficiaries and categories 
  this.service.beneficiaryCategoryList.next([]);
  this.service.beneficiaryListData.next([]);

  // Create requests
  const getBeneficiaryCategoriesRequest = this.service
    .getBeneficiaryCategories(selectedProfile.ProfileId)
    .pipe(
      catchError(() => of ([]))
    );
  const getBeneficiariesListRequest = this.service
    .getBeneficiariesList(selectedProfile.ProfileId).pipe(
      catchError(() => of ([]))
    );

  /* Use a forkJoin to place both requests in parallel and
  then do something when both calls have completed (the
  catchError() operator on each request should keep the
  forkJoin from failing completely should either of the
  calls fail).*/
  return forkJoin({
    categories: getBeneficiaryCategoriesRequest,
    beneficiaries: getBeneficiariesListRequest
  }).pipe(
    tap((res: any) => {
      // Update caches 
      this.service.beneficiaryCategoryList.next(res.categories);
      this.service.beneficiaryListData.next(res.beneficiaries);
      console.log(res.categories);
      console.log(res.beneficiaries);
    })
  );
}

在新方法中,我将不得不创建两个相同的化合器并在const authentication = (state = initialState, action: AuthenticationActions) => { switch (action.type) { case SIGN_UP_SUCCESS: case SIGN_IN_SUCCESS: return { ...state, account: action.payload, }; case SIGN_OUT_SUCCESS: return initialState; default: return state; } }; 中使用它们。 因此,我创建了一个通用助手来匹配多个动作:

.addCase

现在我们可以轻松地将其与import { Action, AnyAction } from '@reduxjs/toolkit'; declare interface TypedActionCreator<Type extends string> { (...args: any[]): Action<Type>; type: Type; } const isOneOf = <ActionCreator extends TypedActionCreator<string>>(actions: ActionCreator[]) => ( (action: AnyAction): action is ReturnType<ActionCreator> => ( actions.map(({ type }) => type).includes(action.type) ) ); 一起使用:

.addMatcher