簡體   English   中英

Redux + Typescript -> 錯誤:不可草擬值上的大小寫縮減器不得返回未定義的 redux

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM