redux 错误:即时生成器返回了一个新值 * 并且 * 修改了其草稿,返回一个新值 * 或者 * 修改草稿

91zkwejq  于 2022-11-12  发布在  其他
关注(0)|答案(7)|浏览(140)

我有我的减速器

const userAuthSlice = createSlice({
    name: "userAuth",
    initialState: {
        token: '',
    },
    reducers: {
        setToken: (state, action) => state.token = action.payload.test,
    },
});

我有我的调度命令

<button
   value={text.sign_in.submit}
   onClick={() => dispatch(userAuthSlice.actions.setToken({test:"test"}))}

/>

当我按下按钮时,我得到的是这个错误:

我已经隔离了一切,以确保这是问题所在,而不是其他。
为什么会弹出此错误?

zbdgwd5y

zbdgwd5y1#

问题是使用了一个没有大括号的箭头函数作为化简函数,因为它相当于一个隐式的return语句,所以,你同时修改了state.token,* 和 *,返回赋值的结果。
根据Immer文档中关于返回数据的内容,有几种方法可以解决此问题:

  • 在赋值前添加void运算符
  • 将赋值括在大括号中,使其成为函数体

因此setToken reducer可以用void更新为

setToken: (state, action) => void(state.token = action.payload.test)
t9eec4r0

t9eec4r02#

了解IMMER的要点
1.如果从配方函数返回除草稿以外的任何值,则该返回值将替换状态
1.您通常希望修改草稿以修改状态,因此在修改草稿后返回草稿是可选的immer将返回最终的草稿
1.如果从recipe函数返回任何其他值,则根据第1点,新的返回值将替换状态
1.第3点是可以的,只有当您不修改配方功能中的草稿时。即您可以选择两个中的一个。
a.修改草稿--〉返回草稿或未定义,两者都可以
B.希望返回一些新值,则根本不接触草稿
现在来回答这个问题。这是你的减速器函数。

(state, action) => state.token = action.payload.test

此函数执行两项操作,
1.修改状态
2.正在返回操作.有效负载.测试
因此它违反了第4点,因此出现了来自Immer库的错误
在这个特定的例子中,目的只是修改状态,所以我们必须使用void撤消现有的返回

setToken: (state, action) => void(state.token = action.payload.test)

但是,Immer库建议使用代码块来确保大型代码库之间的一致性,此代码块隐式返回undefined

setToken: (state, action) => { state.token = action.payload.test }
mv1qrgav

mv1qrgav3#

正确答案
使用代替

const userAuthSlice = createSlice({
    name: "userAuth",
    initialState: {
        token: '',
    },
    reducers: {
        setToken: (state, action) => state.token = action.payload.test,
    },
});

使用此{我刚刚添加了括号}

const userAuthSlice = createSlice({
    name: "userAuth",
    initialState: {
        token: '',
    },
    reducers: {
        setToken: (state, action) => { state.token = action.payload.test}, // <<= Change Here
    },
});
vfwfrxfs

vfwfrxfs4#

对于那些使用React PullState的人,我的问题是语法:
我无言以对:

const onUpdate = (value: any) => {
    someStore.update((s) => (s.value = value));
 };

但必须是:

const onUpdate = (value: any) => {
    someStore.update((s) => {
       s.value = value;
    });
 };

检查我是否用括号{}包围了声明
由于某些原因,不喜欢第一种方法中声明的箭头函数。

piwo6bdm

piwo6bdm5#

而不是

state.token = action.payload.token

使用了

const token = action.payload.token
 state.token = token

常量是不可变的,并且将action.payload内容赋给一个常量为我解决了一个问题(请注意,如果payload是一个对象,则不需要这样做
createSlice的工作示例:

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

export const slice = createSlice({
  name: 'login',
  initialState: {
      username: "Foo",
      password: "AAA",
      authorized : false
  },
  reducers: {
    setUsername: (state, action) => {

      const value = action.payload
      state.username = value // action.payload.username

    },
    setPassword: (state, action) => {

      const value = action.payload
      state.password = value // action.payload.password

    },
    logon: (state, action) => {

      state.username = action.payload.username
      state.password = action.payload.password
      state.authorized = true

    },
    logoff: state => state.authorized = false
  },
});
nr9pn0ug

nr9pn0ug6#

您应该只移除return陈述式和.test

roqulrg3

roqulrg37#

你可能会忘记休息;在reducer.js文件中的语句;

case LOGIN_USER_ERROR_RESET:
        draft.errormsg = '';
        draft.loading = false;
        draft.error = false;
        break;

相关问题