redux 非可绘制值的大小写缩减器不能返回undefined

0aydgbwb  于 2022-11-12  发布在  其他
关注(0)|答案(5)|浏览(415)

我正在做我的项目@reduxjs/toolkit,并创建了如下的UserSlice

import { createSlice, PayloadAction } from "@reduxjs/toolkit";
import { User } from "../../models";

export type UserState = User | null;

export const initialUserState: UserState = null;

const UserSlice = createSlice({
  name: "User",
  initialState: initialUserState,
  reducers: {
    receiveUser: (state: UserState, action: PayloadAction<UserState>) => {
      state = action.payload;
    },
    clearUser: (state: UserState, _action: PayloadAction<void>) => {
      state = null;
    },
    signIn: (
      _,
      _action: PayloadAction<{
        email: string;
        password: string;
      }>
    ) => {},
    signInWithToken: (_, _action: PayloadAction<void>) => {},
  },
});

export default UserSlice;

signInsignInWithToken是动作创建器,仅用于在UserSaga模块中执行动作,因此不执行任何操作。
当我分派signIn动作时,发生下列错误。

index.js:1 Error: A case reducer on a non-draftable value must not return undefined
    at createReducer.ts:163
    at Array.reduce (<anonymous>)
    at createReducer.ts:143
...

这个代码片段模式在我的其他项目中运行良好,但是在这个项目中。我无法找出这个错误的原因,所以我问这个问题。我的代码中是否有任何错误?

rseugnpd

rseugnpd1#

Redux Toolkit的createReducer()允许编写直接改变状态的reducer。这是通过用Immer库中的produce Package reducer调用来实现的。
然而,当当前状态不是Immer的“draftable”时,reducer调用不会用produce Package ,这是基元值的情况,包括null

} else if (!isDraftable(previousState)) {
  // If state is not draftable (ex: a primitive, such as 0), we want to directly
  // return the caseReducer func and not wrap it with produce.
  const result = caseReducer(previousState as any, action)

  if (typeof result === 'undefined') {
    throw Error(
      'A case reducer on a non-draftable value must not return undefined'
    )
  }

  return result
}

因为初始用户状态是null,所以必须从receiveUser() reducer返回新状态。

k5hmc34c

k5hmc34c2#

我相信你不会在所有的reducer中返回状态,因为当使用箭头函数时,对象需要额外的圆括号:

reducers: {
    receiveUser: (state: UserState, action: PayloadAction<UserState>) => ({
      state: action.payload;
    }),
    clearUser: (state: UserState, _action: PayloadAction<void>) => ({
      state : null;
    }),
    signIn: (
      _,
      _action: PayloadAction<{
        email: string;
        password: string;
      }>
    ) => ({}),
    signInWithToken: (_, _action: PayloadAction<void>) => ({}),
  },
9cbw7uwe

9cbw7uwe3#

箭头函数有两种语法形式:

  • (参数1,参数2,...,参数N)=〉{语句}
  • (参数1,参数2,...,参数N)=〉表达式

第一种形式不一定返回值,除非它包含return语句,但第二种形式将返回值。您使用的第一种形式内部没有return,因此它不会返回任何内容。
因为规则是a case reducer on a non-draftable value must not return undefined,所以您可以将函数主体括在括号中,以传回对象常值运算式,如下所示:

params => ({foo: bar})

您可以将代码重写为:

reducers: {
  receiveUser: (state: UserState, action: PayloadAction<UserState>) => ({
    state: action.payload;
  }),
  clearUser: (state: UserState, _action: PayloadAction<void>) => ({
    state : null;
  }),
  signIn: (
    _,
    _action: PayloadAction<{
      email: string;
      password: string;
    }>
  ) => ({}),
  signInWithToken: (_, _action: PayloadAction<void>) => ({}),
},
2izufjch

2izufjch4#

我得到了同样的错误,然后我尝试使用initialState:{value:0}而不是initialState:0。我将initialState值设置为对象,它正在工作。

mfuanj7w

mfuanj7w5#

可能存在两个问题:
1.您可能只需要通过npm i @reduxjs/toolkit@latestyarn add @reduxjs/toolkit@latest将您的@reduxjs/toolkit版本升级到最新版本。
有一个版本有一个bug,如果你用null初始化state,这可能会发生。如果你安装了最新的版本,仍然有问题,请让我知道你在哪个版本,我会尝试重现它。
1.另一个可能的问题是,如果receiveUser中的action.payload实际上是undefined,则会出现该错误,因为不应该返回undefined。

相关问题