无法在Typescript中调度redux操作

时间:2018-07-02 14:53:17

标签: reactjs typescript redux

我打算使用打字稿中的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>
    );
}

}

我遇到以下错误-

  

[加载器]中的错误。/src/components/Counter.tsx:63:54       TS2345:无法将类型“ increment”的参数分配给类型“ AnyAction”的参数。

     

[加载器]中的错误。/src/components/Counter.tsx:65:54       TS2345:无法将类型为“减量”的参数分配给类型为“ AnyAction”的参数。

2 个答案:

答案 0 :(得分:1)

查看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()
  }
...

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

答案 1 :(得分:1)

我通过执行以下操作“修复”了该问题:

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

如果您仅向其添加一个动作类型为“ AnyAction”的空化器,则似乎可以解决该问题。

显然,这实际上并不能解决根本问题,但是对于那些对上述解决方案的结果感到满意的人,这是一种肮脏的方式。

自行决定使用。