无法在 Typescript 中调度 redux 操作

Posted

技术标签:

【中文标题】无法在 Typescript 中调度 redux 操作【英文标题】:Unable to dispatch redux action in Typescript 【发布时间】:2018-12-10 20:12:06 【问题描述】:

我打算在 typescript 中使用 react redux 创建一个简单的计数器。

我已经通过以下方式定义了我的商店,其中包含动作和减速器,但不确定如何使用特定动作调用调度

import * as React from 'react';
import  createStore, Action, Reducer  from 'redux';

export interface CounterState 
    counter: number;


export enum ActionTypes 
    INCREMENT = 'increment',
    DECREMENT = 'decrement'


export interface IncAction  type: ActionTypes.INCREMENT 
export interface DecAction  type: ActionTypes.DECREMENT 

export type CounterAction = IncAction | DecAction;

const reducer: Reducer<CounterState> = (state: CounterState = counter: 0, action: CounterAction) => 
    switch (action.type) 
        case ActionTypes.INCREMENT:
            return  ...state, counter: state.counter + 1;
        case ActionTypes.DECREMENT:
            return  ...state, counter: state.counter - 1;
        default:
            return state;
    
;

let store = createStore(reducer,  counter: 0 );

以下是我的反应组件Counter 的样子

interface IProps 

interface IState 

export default class Counter extends React.Component<IProps, IState> 

private unsubscribe: Function;

constructor(props: IProps, context?: any) 
    super(props, context);


componentDidMount() 
    this.unsubscribe = store.subscribe(() => this.render());


componentWillUnmount() 
    this.unsubscribe();


render() 
    const  counter  = store.getState();
    return (
        <div>
            <p>
                <label>Counter: </label><b>#counter</b>
            </p>
            <button onClick=e => store.dispatch('increment') >+</button>
            <span style= padding: "0 5px"  />
            <button onClick=e => store.dispatch('decrement') >-</button>
        </div>
    );

我收到以下错误 -

[at-loader] 中的错误 ./src/components/Counter.tsx:63:54 TS2345:“增量”类型的参数不可分配给“AnyAction”类型的参数。

[at-loader] ./src/components/Counter.tsx:65:54 中的错误 TS2345:“减量”类型的参数不可分配给“AnyAction”类型的参数。

【问题讨论】:

【参考方案1】:

我通过这样做“修复”了这个问题:

const _ = (state: any = 0, _: AnyAction) => state;
const root = combineReducers(
    _,
    applicationStatusReducer,
    ...
);

如果你只添加一个动作类型为“AnyAction”的空reducer,似乎可以解决这个问题。

显然这实际上并没有解决根本问题,但对于满足于上述修复结果的人来说,这是一种肮脏的做法。

自行决定使用。

【讨论】:

【参考方案2】:

查看ActionAnyAction的实际类型定义:

export interface Action 
  type: any;


export interface AnyAction extends Action 
  // Allows any extra properties to be defined in an action.
  [extraProps: string]: any;

它必须是一个对象,并且它必须有一个 type 属性而不仅仅是一个 string

您需要一个至少返回具有type 属性的对象的操作创建器。你也可以直接传递这个对象,这是我假设你尝试做的:

store.dispatch(type: ActionTypes.INCREMENT)

我还建议使用connect HOC 将状态连接到您的组件,因为当您的商店中的计数器值发生变化时,const counter = store.getState(); 不会触发重新渲染。如果你想要一个更基本的例子:

...
  this.unsubscribe : () => void

  componentDidMount() 
    this.unsubscribe = store.subscribe(() => this.setState( store.getState() ))
  

  componentWillUnmount() 
    this.unsubscribe()
  
...

然后通过const counter = this.state;render引用组件的本地状态

【讨论】:

我通过store.dispatch(type: ActionTypes.INCREMENT) 解决了这个问题。还必须在 counter 中解构 store.getState() 但仍然 counter 保持 0 i:( 我已经更新了我的答案,对于任何更复杂的问题,您确实需要使用react-redux --> github.com/reduxjs/react-redux

以上是关于无法在 Typescript 中调度 redux 操作的主要内容,如果未能解决你的问题,请参考以下文章

使用 typescript 将异步操作发送到 redux 调度

如何使用 redux-thunk 和 TypeScript 调度 ThunkAction

使用 TypeScript 在 React 组件外部调度 Redux Thunk 操作

Redux-Toolkit createAsyncThunk with Typescript

useEffect TypeScript 错误中的 Redux 操作?

无法在 redux 、 react/typescript 中使用 rootReducer