【问题标题】:Replace state of multiple slices using redux toolkit使用 redux 工具包替换多个切片的状态
【发布时间】:2022-12-11 04:23:48
【问题描述】:

您如何使用 redux 工具包将包含多个切片的商店的状态替换为其他一些新状态?

您可以使用extraReducers将整个商店恢复到初始状态:是否可以使用相同的机制将商店状态更改为初始状态以外的其他状态?

例如,你会有这样的东西:

const aSlice = createSlice({ 
  name: 'a', 
  initialState: {a: 1}, 
  reducers: {
    someReducer(state, action) {...}
  }
})
const bSlice = createSlice({ 
  name: 'b', 
  initialState: {b: 'foo'}, 
  reducers: {}
})

const store = configureStore({
  reducer: {
    aReducer: aSlice.reducer,
    bReducer: bSlice.reducer,
  }
});

export type RootState = ReturnType<typeof store.getState>

在反应组件中,您可以使用以下方式更新状态:

const dispatch = useDispatch();
dispatch(someReducer({...}));

你会如何用这样的东西替换整个商店的状态:

{
  "aReducer": {"a": 2},
  "bReducer": {"b": "bar"},
}

【问题讨论】:

    标签: reactjs typescript redux redux-toolkit


    【解决方案1】:

    您可以为此使用 extraReducer。

    您可以将任意有效负载(如 {"a": 2, "b": "bar"} 传递给创建的操作。使用 createAction 您可以拥有不“属于”特定切片的操作,请参阅:https://redux-toolkit.js.org/api/createAction 并在两个仅使用的切片中实现 extraReducers他们的有效载荷部分。

    【讨论】:

    • 这可行,但它不是类型安全的,因为您不知道 createStore 之后的 RootState 类型:const replaceWith = createAction&lt;any&gt;('REPLACE_WITH'),并添加到每个切片:extraReducers: (builder) =&gt; builder.addCase(replaceAll, (state: action) =&gt; action.payload.xReducer)。您将如何使其类型安全?
    • 您可以通过定义 rootReducer 并导出其 ReturnType 来获取 RootState 类型,如此处所述 redux-toolkit.js.org/usage/… 之后您可以执行以下操作:export const myAction = createAction&lt;RootState&gt;('MyActionType');
    • 但是,如示例中所示,您必须首先定义 myAction,因为您希望在创建切片时使用它,最终创建您的 rootReducer(和 RootState)。在定义myAction 时如何使用 RootState?
    • 嗯,是的,这听起来不应该起作用。我有一个类似的用例,其中这种方法在没有 TypeScript 抱怨的情况下起作用。但也许我只是在路上的某个地方不小心松开了类型安全,所以我不确定这是否是你正在寻找的。但是如果你很好奇代码在这里:github.com/dermeck/feeds-sidebar/blob/rootstate-refactor/src/…
    【解决方案2】:

    你确实可以使用extraReducers类型安全,正如 dermeck 所建议的那样。

    一个最小的例子是:

    
    import {combineReducers, configureStore, createAction, createSlice, PayloadAction} from "@reduxjs/toolkit";
    
    export const replaceWith = createAction<RootState>('REPLACE_WITH');
    
    
    const initialState: { a: number } = {
      a: 0
    }
    
    export const aSlice = createSlice({
      name: 'a-slice',
      initialState,
      reducers: {
        reduce(state, action: PayloadAction<number>) {
          return {a: action.payload}
        }
      },
      extraReducers: (builder) => {
        builder.addCase(replaceWith, (_, action) => {
          return {
            ...action.payload.aReducer,
          };
        });
      },
    });
    
    export const bSlice = createSlice({
      name: 'b-slice',
      initialState: {},
      reducers: {/* TODO */},
      extraReducers: (builder) => {/* TODO */},
    });
    
    const rootReducer = combineReducers({
      aReducer: aSlice.reducer,
      bReducer: bSlice.reducer
    });
    
    const store = configureStore({
      reducer: rootReducer,
    });
    
    export type RootState = ReturnType<typeof rootReducer>;
    

    最后,在您的 React 组件中,您可以执行以下操作:

    const dispatch = useDispatch();
    dispatch(replaceWith(newState));
    

    【讨论】:

      【解决方案3】:

      根据定义,Reducers 只能访问它们拥有的状态部分。所以,如果我有 {users: usersReducer, posts: postsReducer},usersReducer 根本无法访问 posts 状态切片。 How can I access state of another slice in redux with redux-toolkit?

      所以你必须分派两个切片的两个动作,每个单独的 reducer 都会单独更新它的状态。

      【讨论】:

      • 我认为这可以通过 extraReducers 实现,它允许响应除它生成的类型之外的其他操作类型 (docs)。但是这样的动作会是什么样子呢?
      【解决方案4】:

      RHSTEGRTHRNHGRSHDSNFGXBDFGDFNHXGBFXFNHMNX

      【讨论】:

        猜你喜欢
        • 2022-12-31
        • 2020-07-30
        • 2021-11-21
        • 2021-06-20
        • 1970-01-01
        • 2022-09-29
        • 2020-11-17
        • 2021-02-06
        • 2020-10-08
        相关资源
        最近更新 更多