如何使用 Typescript 构建一个 react-redux reducer 来处理不同类型的有效负载?
How to structure a react-redux reducer with Typescript to handle different kinds of payloads?
所以,我正在尝试使用 React、Redux 和 TypeScript 构建一个 Todo 应用程序。将有一些待办事项页面,每个页面都会涉及待办事项。
以下是必要的类型和 Todos 状态。
export type Todo = {
name: string;
due: Date;
color: string;
pageId: string;
};
export type TodosByPageId = {
[page: string]: Todo[];
}
export type TodosState = {
byPageId: TodosByPageId;
curPageId: string;
};
定义我的常量和动作后,我导出下面给定的减速器动作:
export type TodosAction = SetTodos | AddTodo | DeleteTodo | UpdateTodo | SetTodoPageId;
基本上
- AddTodo、DeleteTodo 和 UpdateTodo 接受一个待办事项,有效载荷是一个待办事项
- SetTodos 采用 Todo[] 并且有效载荷是 Todo[]
- SetTodoPageId 接受字符串,有效负载为字符串
然后我开始定义todosReducer:
const initalState: TodosState = {
byPageId: {},
curPageId: '',
}
const todosReducer = (state: TodosState, action: TodosAction): TodosState => {
switch(action.type) {
case Constants.ADD_TODO:
return state; // TODO
case Constants.DELETE_TODO:
return state; // TODO
case Constants.SET_TODOS:
return state; // TODO
case Constants.SET_TODO_PAGE_ID:
return { ...state, curPageId: action.payload };
case Constants.UPDATE_TODO:
return state; // TODO
default:
return state;
}
}
在我处理的行 SET_TODO_PAGE_ID
给了我错误
Type 'string | Todo | Todo[]' is not assignable to type 'string'.
Type 'Todo' is not assignable to type 'string'.
这是有道理的。每种情况下的类型转换似乎都不对,所以我想问一下这种情况下什么是更好的设计?
顺便说一下,我知道 redux 工具包是推荐的方式,但我只是想学习这两种风格。
我是 Redux 维护者。
如您所述:这里的第一个答案是 you should be using Redux Toolkit. We specifically recommend against trying to write reducers and actions by hand today. We do have a "Redux Fundamentals" tutorial 在我们的文档中显示了如何 hand-write Redux 代码,但 仅 以便您了解基本机制。对于任何实际的应用程序,您应该使用 RTK。
第二个观察结果是 you should not be writing TS action type unions - 它们没有提供任何实际好处,并且实际上并不代表代码的运行方式。
请改用 our Redux TS Quick Start docs page 中显示的方法。
所以,我正在尝试使用 React、Redux 和 TypeScript 构建一个 Todo 应用程序。将有一些待办事项页面,每个页面都会涉及待办事项。
以下是必要的类型和 Todos 状态。
export type Todo = {
name: string;
due: Date;
color: string;
pageId: string;
};
export type TodosByPageId = {
[page: string]: Todo[];
}
export type TodosState = {
byPageId: TodosByPageId;
curPageId: string;
};
定义我的常量和动作后,我导出下面给定的减速器动作:
export type TodosAction = SetTodos | AddTodo | DeleteTodo | UpdateTodo | SetTodoPageId;
基本上
- AddTodo、DeleteTodo 和 UpdateTodo 接受一个待办事项,有效载荷是一个待办事项
- SetTodos 采用 Todo[] 并且有效载荷是 Todo[]
- SetTodoPageId 接受字符串,有效负载为字符串
然后我开始定义todosReducer:
const initalState: TodosState = {
byPageId: {},
curPageId: '',
}
const todosReducer = (state: TodosState, action: TodosAction): TodosState => {
switch(action.type) {
case Constants.ADD_TODO:
return state; // TODO
case Constants.DELETE_TODO:
return state; // TODO
case Constants.SET_TODOS:
return state; // TODO
case Constants.SET_TODO_PAGE_ID:
return { ...state, curPageId: action.payload };
case Constants.UPDATE_TODO:
return state; // TODO
default:
return state;
}
}
在我处理的行 SET_TODO_PAGE_ID
给了我错误
Type 'string | Todo | Todo[]' is not assignable to type 'string'.
Type 'Todo' is not assignable to type 'string'.
这是有道理的。每种情况下的类型转换似乎都不对,所以我想问一下这种情况下什么是更好的设计?
顺便说一下,我知道 redux 工具包是推荐的方式,但我只是想学习这两种风格。
我是 Redux 维护者。
如您所述:这里的第一个答案是 you should be using Redux Toolkit. We specifically recommend against trying to write reducers and actions by hand today. We do have a "Redux Fundamentals" tutorial 在我们的文档中显示了如何 hand-write Redux 代码,但 仅 以便您了解基本机制。对于任何实际的应用程序,您应该使用 RTK。
第二个观察结果是 you should not be writing TS action type unions - 它们没有提供任何实际好处,并且实际上并不代表代码的运行方式。
请改用 our Redux TS Quick Start docs page 中显示的方法。