Reactjs 反应&;Redux-“是的;动作必须是普通对象”;

Reactjs 反应&;Redux-“是的;动作必须是普通对象”;,reactjs,typescript,redux,Reactjs,Typescript,Redux,我在想为什么这不起作用 我在Typescript上使用React with Redux 我有以下代码: import * as React from 'react'; import * as ReactDOM from 'react-dom'; import {Action} from 'redux'; /** Redux Action **/ class AddTodo implements Action { type: string; id: number; text:

我在想为什么这不起作用

我在Typescript上使用React with Redux

我有以下代码:

import * as React from 'react';
import * as ReactDOM from 'react-dom';
import {Action} from 'redux';

/** Redux Action **/
class AddTodo implements Action {
   type: string;
   id: number;
   text: string;
   constructor(id: number, text: string) {
       this.type = 'ADD_TODO';
       this.id = id;
       this.text = text;
   }
}

// ...

class TodoApp extends React.Component {
   public render(): JSX.Element {
      return (
          <div>
              <button onClick={() => {
                 store.dispatch(new AddTodo(0, 'Test'));
              }}>
                 Add Todo
              </button>
          </div>
      );
   }
}

// ...
import*as React from'React';
从“react dom”导入*作为react dom;
从'redux'导入{Action};
/**重演行动**/
类AddTodo实现操作{
类型:字符串;
id:编号;
文本:字符串;
构造函数(id:编号,文本:字符串){
this.type='ADD_TODO';
this.id=id;
this.text=文本;
}
}
// ...
类TodoApp扩展了React.Component{
public render():JSX.Element{
返回(
{
store.dispatch(新的AddTodo(0,'Test'));
}}>
添加待办事项
);
}
}
// ...
单击该按钮时,控制台上出现以下错误:

未捕获错误:操作必须是普通对象。使用自定义中间件进行异步操作

我不明白为什么Redux会假设这是一个异步操作或复杂对象

我的减速器甚至没有被执行。它们看起来像这样:

const todoReducer: Reducer<Todo> = (state: Todo, action: Action): Todo => {
   if (action instanceof AddTodo)
      return { id: action.id, text: action.text, completed: false } as Todo;
   // ...
   else
      return state;
};

const todosReducer: Reducer<Todo[]> = (state: Todo[] = [], action: Action): Todo[] => {
   if (action instanceof AddTodo)
       return [...state, todoReducer(undefined, action)];
   // ...
   else
       return state;
}
const todoReducer:Reducer=(状态:Todo,操作:action):Todo=>{
if(AddTodo的操作实例)
返回{id:action.id,text:action.text,completed:false}作为Todo;
// ...
其他的
返回状态;
};
常量todosReducer:Reducer=(状态:Todo[]=],操作:操作):Todo[]=>{
if(AddTodo的操作实例)
返回[…状态,todoReducer(未定义,动作)];
// ...
其他的
返回状态;
}
如果传入
{type:'ADD_TODO',id:0,text:'Test'}
而不是
新操作(0,'Test')
,则错误消失,但由于减速器上的条件,我的操作未正确执行


你知道这里发生了什么吗?

这是丹·阿布拉莫夫自己解释的:

基本上,如果使用我的方法,操作的序列化和反序列化(记录/重播功能)将不起作用,因为类型信息不会持久化

引用丹的话:

换句话说,这是一种反模式:

如果我们能够让TypeScript用户使用它,我知道JavaScript用户会受到诱惑,并且会滥用它,因为许多来自传统OO语言的人习惯于以这种方式编写代码。然后,他们将失去在Redux中录制/重播的好处

Redux的一个要点是强制执行一些我们认为很重要的限制,如果不强制执行,就不允许以后使用丰富的工具。如果我们让人们使用类来执行动作,他们就会这样做,实现像redux recorder这样的东西是不可能的,因为不能保证人们使用普通的对象动作。特别是如果样板项目突然决定采用类,因为“哇,现在允许了,这一定是个好主意”


请提供AddToDo的代码段好吗?您已经创建了一个“对象构造函数”,而不是错误消息所述的普通对象@我已经提供了。它是位于上述代码顶部的类。如果你是指add逻辑,那么它就在我在文章底部发布的reducer上。@ctrlplusb我使用的是TypeScript,而不是babel。从TS生成的JS代码不包含任何
\u classCallCheck
方法。@ctrlplusb我有一个
返回状态作为默认情况。无论如何,如果操作未被识别,则不应抛出此类错误。
function reducer(state, action) {
   if (action instanceof SomeAction) {
     return ...
   } else {
     return ...
   }
}