[英]React/Redux reducer typescript error (Type 'undefined' is not assignable to type ISupplierState)
[英]Redux + Typescript -> Error: A case reducer on a non-draftable value must not return undefined redux
我正在尝试在我的 redux 应用程序中导入 typescript。 我像这样使用 redux 工具包 createSlice function:
const slice = createSlice({
name: sliceName,
initialState,
reducers: {
updateMode(state: SliceState, action: PayloadAction<ModePayload>) {
state = action.payload.mode;
},
},
});
当我调度 updateMode 操作时,我收到以下错误:
Error: A case reducer on a non-draftable value must not return undefined
但是我的 action.payload 定义明确,并且 redux 工具包是最新的。 它与我的代码有关,但我无法弄清楚......
我尝试在 updateMode 中返回 state 并且它可以工作,但我收到 TypeScript 错误:
Type '(state: SliceState, action: { payload: ModePayload; type: string; }) => SliceState' is not assignable to type 'CaseReducer<"SHOW_LIST", { payload: any; type: string; }> | CaseReducerWithPrepare<"SHOW_LIST", PayloadAction<any, string, any, any>>'.
Type '(state: SliceState, action: { payload: ModePayload; type: string; }) => SliceState' is not assignable to type 'CaseReducer<"SHOW_LIST", { payload: any; type: string; }>'.
Type 'SliceState' is not assignable to type 'void | "SHOW_LIST"'.
Type '"SHOW_SKILL"' is not assignable to type 'void | "SHOW_LIST"'
有人可以向我解释我做错了什么吗?
在我的完整代码下方:
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
type SliceState = "SHOW_LIST" | "SHOW_SKILL";
let initialState: SliceState = "SHOW_LIST";
const sliceName = "mode";
interface ModePayload {
mode: SliceState;
}
//--- Slice reducer ---
const modeSlice = createSlice({
name: sliceName,
initialState,
reducers: {
updateMode(state: SliceState, action: PayloadAction<ModePayload>) {
return (state = action.payload.mode);
},
},
});
export const { updateMode } = modeSlice.actions;
export default modeSlice.reducer;
我是 Redux 维护者和 Redux 工具包的创建者。
实际问题出在这一行:
state = action.payload.mode;
这实际上并没有完成任何有用的事情。 Immer 通过跟踪现有值的突变来工作,例如state.someField = 123
。 您编写的行仅将本地state
变量更改为指向其他内容。
Immer 要求您要么返回一个全新的 state 值,要么改变现有的 state。 那行代码也没有。 相反,reducer 最终只返回undefined
,因此返回错误。
如果你想完全替换现有的 state,你应该只做return action.payload.mode
。
另外,作为旁注:如果initialState
输入正确,则不必为每个减速器提供state
的类型,因为它会被推断出来。
在文档之后,您可能必须将您的类型转换如下:
const modeSlice = createSlice({
name: sliceName,
initialState: initialState as SliceState,
reducers: {
updateMode(state: SliceState, action: PayloadAction<ModePayload>) {
return (state = action.payload.mode);
},
},
});
通常你会有这样的东西
type SliceState = {
mode: string;
};
interface ModePayload {
mode: string;
}
const initialState: SliceState = {
mode: 'initial mode',
};
//--- Slice reducer ---
const modeSlice = createSlice({
name: 'modeSlice',
initialState,
reducers: {
updateMode(state, action: PayloadAction<ModePayload>) {
state.mode = action.payload.mode;
},
},
});
export const { actions, reducer, name: sliceKey } = modeSlice;
然后无论你在哪里导入这个切片,你必须分发你的动作,你就会得到类似的东西。
import {actions} from '../mode-slice'
....
// somewhere in your component/view or whatever
dispatch(actions.updateMode({mode: 'new mode'}))
本质上,您的切片包含由 redux 存储的全局 state 的切片,您正在切片并仅操作它的切片。 切片包含减速器和允许您操纵状态(状态切片)的操作。
React Boilerplate CRA在这里有一些很好的解释。
谢谢大家的回答。
我合并了你的两个答案,我得到了以下结果,这正是我想要的:
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
type SliceState = "SHOW_LIST" | "SHOW_SKILL";
let initialState: SliceState = "SHOW_LIST";
const sliceName = "mode";
interface ModePayload {
mode: SliceState;
}
//--- Slice reducer ---
const modeSlice = createSlice({
name: sliceName,
initialState: initialState as SliceState,
reducers: {
updateMode(state, action: PayloadAction<ModePayload>) {
return action.payload.mode;
},
},
});
export const { updateMode } = modeSlice.actions;
export default modeSlice.reducer;
这使我可以在我的全局 state 中使用我的模式切片等于“SHOW_LIST”|| “SHOW_SKILL”,这是我一开始想要的。 如果我的模式需要更多数据,我肯定会让我的切片 state 像这样:
{
mode: "SHOW_LIST",
otherAttribute: otherValue,
...,
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.