【问题标题】:Unable to dispatch redux action in Typescript无法在 Typescript 中调度 redux 操作
【发布时间】: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”类型的参数。

【问题讨论】:

    标签: reactjs typescript redux


    【解决方案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
      猜你喜欢
      • 2020-05-30
      • 1970-01-01
      • 2021-09-01
      • 1970-01-01
      • 2017-11-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-23
      相关资源
      最近更新 更多