redux - 如何正确使用 redux toolkit 的 preloadedState 和 createSlice?

标签 redux redux-toolkit

我正在尝试迁移到 redux 工具包,但刚刚遇到了一个问题。
这是一个简单的计数器切片示例。

import { createSlice } from "@reduxjs/toolkit";

const initialState = {
  value: 0,
};

export const counterSlice = createSlice({
  name: "counter",
  initialState,
  reducers: {
    increment: (state) => {
      state.value += 1;
    },
    decrement: (state) => {
      state.value -= 1;
    },
  },
});

export const { increment, decrement } = counterSlice.actions;
export default counterSlice.reducer;

这是一个用 configureStore 创建的商店。
import { configureStore } from "@reduxjs/toolkit";
import counterReducer from "./slice";

export const store = configureStore({
  reducer: {
    counter: counterReducer,
    // later, many other reducers will be added here.
  },
});

还是有什么问题。
但是如果我引入preloadedState,就存在问题。
const store = configureStore({
    reducer: counterReducer,
    preloadedState: {
      counter: {
         value: 10
      }
    },
  });
如果我像下面这样记录商店的状态,它会按预期记录。
   // without using preloadedState, it results to {counter: {value: 0}}
   console.log(store.getState())
   // with using preloadedState, it results to {counter: {value: 10}}
   console.log(store.getState())
但是在使用 slice reducer 时会出现一个问题,因为 slice reducer 使用自己的状态。
   ...
     reducers: {
       increment: (state) => {
         state.value += 1;  // not work anymore if using preloadedState. we have to use state.counter.value instead.
       },
       decrement: (state) => {
         state.value -= 1;  // not work anymore if using preloadedState. we have to use state.counter.value instead.
       },
     },
   ...
相反,我们必须使用,
   ...
     reducers: {
       increment: (state) => {
         state.counter.value += 1; 
       },
       decrement: (state) => {
         state.counter.value -= 1;
       },
     },
   ...
那么问题来了,我们是否必须添加条件语句,根据我们是否使用 preloadedState 来分离 slice reducer 内部的逻辑?
每当提供 preloadedState 时,如果 slice reducer 使用 preloadedState 而不是使用它自己的状态,那就太好了。有没有更好的办法?
谢谢你。

最佳答案

如果你查看你的 Redux Devtools 浏览器扩展,你会注意到 - 因为你只有一个 reducer 并且你将它作为根 reducer 传入,你的 state 的形状为

{
  value: 10
},
此时您的正常状态只是没有计数器 reducer 的子键,因为您的整个状态是计数器 reducer 。
如果你想让你的状态有一个合理的结构(并且在 future 能够使用多个 reducer ),你必须添加 reducer键作为对象:
const store = configureStore({
    reducer: {
      counter: counterReducer,
    },
    preloadedState: {
      counter: {
         value: 10
      }
    },
  });
正如您将在 devtools 中注意到的那样,现在您的状态结构是您所期望的 - 并且预加载状态也将匹配。
但请记住,从现在开始,在选择器中,您必须useSelector(state => state.counter.value)

关于redux - 如何正确使用 redux toolkit 的 preloadedState 和 createSlice?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68572170/

相关文章:

checkbox - 如何在嵌套的 MenuItem 中使用复选框

reactjs - Redux Toolkit : Error: Actions must be plain objects. 使用自定义中间件进行异步操作

reactjs - creactAsyncThunk 中的 action.payload 未定义

javascript - 有没有办法禁用 Redux 警告 : A non-serializable value was detected in the state

reactjs - React Redux 组合 reducer

reactjs - 使用对象剩余删除嵌套对象

javascript - React(Redux + Redux Saga)和 MVC

javascript - 如何在 ReactJS + Redux 中检查数组中的每个对象?

reactjs - 在 rtk 查询中使用条件 header 的正确方法?

redux - 路径 'emailReducer.emails.0' 中的错误 : Invariant failed: A state mutation was detected between dispatches,