Redux开关大小写在reducer ts文件上出错



代码是由webpack编译的,但我在浏览器控制台上遇到了一个错误。

问题似乎出在这一行:"开关(动作类型(">

这是代码:

/减速器

import { produce } from 'immer';
import ActionTypeKeys from './actionTypeKeys';
import { AuthAction } from './actionTypes';
export type AuthState = {
isLoggedIn: boolean;
};
const initialState = { isLoggedIn: false };
export const authReducer = produce(
(action: AuthAction, draft: AuthState = initialState) => {
switch (action.type) {
case ActionTypeKeys.IS_LOGIN:
draft.isLoggedIn = action.payload;
break;
default:
throw new Error('No matching ActionTypeKeys was found!');
}
return draft;
}
);

/actionTypeKeys

enum ActionTypeKeys {
REFRESH_TOKEN = 'auth/REFRESH_TOKEN',
IS_LOGIN = 'auth/IS_LOGIN',
}
export default ActionTypeKeys;

控制台错误:

reducer.ts:14 Uncaught TypeError: Cannot read properties of undefined (reading 'type')
at reducer.ts:14:18
at immer.esm.js:1:16007
at e.produce (immer.esm.js:1:16373)
at immer.esm.js:1:15969
at redux.js:436:1
at Array.forEach (<anonymous>)
at assertReducerShape (redux.js:434:1)
at combineReducers (redux.js:499:1)
at Module../src/store/rootReducer.ts (rootReducer.ts:11:43)
at __webpack_require__ (bootstrap:24:1)

错误触发线路"开关(动作类型(">

我不知道该怎么解决。

有人能把灯给我吗?

似乎在执行dispatch(undefined)dispatch()dispatch(something())时,something意外返回undefined而不是操作对象。

除此之外:您的throw new Error('No matching ActionTypeKeys was found!');是一个错误-在Redux中,当没有找到匹配的操作时,您总是必须使用return state。由于每个动作总是传递给每个控制器;INIT";操作在dev中是随机的,可以肯定的是,每个reducer都会看到至少一个您不知道的操作。

此外,一般来说,你在这里写的是一种非常古老的Redux风格。Modern Redux使用官方的Redux工具包(这是自2019年以来的官方建议(,不使用switch。。case reducers、ACTION_TYPES、TypeScript操作类型联合以及此后发生的许多其他变化。尤其是使用TypeScript,您可能会节省3/4以上的代码,转而使用现代方法。在这一点上,我们甚至明确建议而不是使用操作联合类型。请查看官方Redux Essentials教程,因为您可能正在使用非常过时的文档。

我更新了类似以下内容的代码:

import { createSlice } from '@reduxjs/toolkit';
import { User } from '../../common/interfaces/User';
export type AuthState = { user: User | null; isLogged: boolean };
const initialState: AuthState = { user: null, isLogged: false };
export const userSlice = createSlice({
name: 'auth',
initialState,
reducers: {
setUserAction: (state, action) => {
state.user = action.payload;
},
loginAction: (state, action) => {
state.isLogged = action.payload;
},
},
});
export const { setUserAction, loginAction } = userSlice.actions;
export default userSlice.reducer;

它运行得很好!

我认为,用produce创建减速器是不正确的。

  1. initialState作为单独的producearg传递
  2. 无需从回调中返回草稿
  3. reducer回调中没有默认参数值
  4. 在意外的操作类型上抛出错误是一种糟糕的做法

尝试以下操作:

import { produce } from 'immer';
// ...
const authReducer = produce((draft: AuthState, action: AuthAction) => {
switch (action?.type) {
case ActionTypeKeys.IS_LOGIN:
draft.isLoggedIn = action.payload;
break;  
}
}, initialState);

请参见示例。

最新更新