我打算在打字稿中使用 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:类型为"增量"的参数不可分配给类型为"任何操作"的参数。
错误 in [at-loader] ./src/components/Counter.tsx:65:54 TS2345:类型为"递减"的参数不可分配给类型为"AnyAction"的参数。
看看Action
和AnyAction
的实际类型定义:
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
我通过这样做"修复"了这个问题:
const _ = (state: any = 0, _: AnyAction) => state;
const root = combineReducers({
_,
applicationStatusReducer,
...
});
如果您只是添加一个操作类型为"AnyAction"的空化简器,它似乎可以解决问题。
显然,这实际上并没有解决根本问题,但对于对上述修复结果感到满意的人来说,这是一种肮脏的方法。
自行决定使用。