【问题标题】:type error with redux-thunk when using connect使用 connect 时使用 redux-thunk 键入错误
【发布时间】:2018-10-21 23:39:19
【问题描述】:

我正在使用带有 typescript 的 redux 和 redux-thunk。我正在尝试使用 mapDispatchToProps 通过 connect() 向组件注入一个简单的 thunk 动作创建器。

操作

export enum TestActionTypes {
  THUNK_ACTION = "THUNK_ACTION"
}

export interface ThunkAction {
  type: TestActionTypes.THUNK_ACTION;
}

export type TestAction = ThunkAction;

动作创作者

export function thunkActionCreator() {
  return function(dispatch: Dispatch<any>) {
    dispatch({ type: TestAction.THUNK_ACTION });
  };

连接组件

interface DemoScreenState {}

interface OwnProps {}

interface StateProps {}

interface DispatchProps {
  testThunk: () => void;
}

type DemoScreenProps = StateProps & DispatchProps & OwnProps;

class DemoScreen extends React.Component<
  DemoScreenProps,
  DemoScreenState
> {
  constructor(props: DemoScreenProps) {
    super(props);
  }

  componentDidMount() {
    this.props.testThunk();
  }

  render() {
    return null;
  }
}

function mapStateToProps(state: any): StateProps {
  return {};
}

function mapDispatchToProps(dispatch: Dispatch<any>): DispatchProps {
  return {
    testThunk: () => dispatch(thunkActionCreator())
  };
}

export default connect<StateProps, DispatchProps, OwnProps>(
  mapStateToProps,
  mapDispatchToProps
)(DemoScreen);

商店

 import { createStore, applyMiddleware } from "redux";
 import rootReducer from "./RootReducer";
 import thunk from "redux-thunk";

 const store = createStore(rootReducer, applyMiddleware(thunk));

 export default store;

但是,我在使用 connect() 时遇到了两个问题。首先,我在 mapDispatchToProps 中声明 testThunk 时出现类型错误。

'(dispatch: Dispatch) => void' 类型的参数不能分配给'Action' 类型的参数。类型 '(dispatch: Dispatch) => void' 中缺少属性 'type'。 我不知道如何处理这个问题,因为根据定义,thunk 与普通操作不同。

* EDIT 24/10/2018 * 参见下面的答案,使用:

"@types/react-redux": "^6.0.9",
"react": "16.3.1",
"react-native": "~0.55.2",
"react-redux": "^5.0.7",
"redux": "^4.0.1",
"redux-thunk": "^2.3.0"

【问题讨论】:

  • 我们可以看看你在哪里配置 thunk 中间件吗?
  • 我已经更新了这个问题。我没有配置 thunk 中间件,我只是从“redux-thunk”中导入它,并使用“redux”中的 applyMiddleware 以 thunk 作为参数初始化存储。
  • 这可能有帮助吗? github.com/reduxjs/redux-thunk/issues/…(“dupski 于 2017 年 5 月 2 日发表评论”——当天第一个来自 dupski 的评论)

标签: typescript redux react-redux redux-thunk


【解决方案1】:

我终于设法获得了一个正确类型的连接组件,主要使用它作为起点https://github.com/reduxjs/redux-thunk/blob/master/test/typescript.ts 来进行正确的异步操作创建者类型。 关键是正确键入您的商店,并使用来自 redux-thunk 的 ThunkDispatch 和 ThunkAction。

Store.tsx

import { createStore, applyMiddleware, combineReducers } from "redux";
import { playground, IState } from "./reducer";
import thunk, { ThunkMiddleware } from "redux-thunk";
import { IActions } from "./actions";

export interface RootState {
  playground: IState;
}

export type RootActions = IActions;

const rootReducer = combineReducers({ playground });

const store = createStore<RootState, RootActions, {}, {}>(
  rootReducer,
  applyMiddleware(thunk as ThunkMiddleware<RootState, RootActions>)

Actions.tsx

import { Action } from "redux";
import { ThunkAction } from "redux-thunk";
import { RootState, RootActions } from "./store";

type ThunkResult<R> = ThunkAction<R, RootState, undefined, RootActions>;

//Actions
export enum TestActionTypes {
  THUNK_ACTION = "THUNK_ACTION",
}

export interface AsyncAction extends Action {
  type: TestActionTypes.THUNK_ACTION;
}

export type IActions = AsyncAction;

//Action creator
export function testAsyncActionCreator(): ThunkResult<void> {
  return (dispatch, getState) => {
    console.log(getState);
    dispatch({ type: TestActionTypes.THUNK_ACTION });
  };
}

Reducer.tsx

import { IActions, TestActionTypes } from "./actions";
import { Reducer } from "redux";

export interface IState {}

const defaultValue: IState = {};

export const playground: Reducer<IState, IActions> = (
  state = defaultValue,
  action
) => {
  switch (action.type) {
    default:
      return state;
  }
};

ConnectedComponent.tsx

...
import { connect } from "react-redux";
import { RootState, RootActions } from "./redux/store";
import { syncActionCreator, testGetState } from "./redux/actions";
import { ThunkDispatch } from "redux-thunk";

interface OwnProps {}

interface StateProps {}

interface DispatchProps {
  test: () => void;
}

type Props = OwnProps & StateProps & DispatchProps;

class DumbContainer extends React.Component<Props> {
  render() {
    return (
      ...
    );
  }
}


const mapStateToProps = (state: RootState): StateProps => {
  return {
    text: state.playground.text
  };
};

const mapDispatchToProps = (
  dispatch: ThunkDispatch<RootState, undefined, RootActions>
): DispatchProps => {
  return {
    test: () => {
      dispatch(testAsyncActionCreator());
    }
  };
};

export default connect<StateProps, DispatchProps, OwnProps, RootState>(
  mapStateToProps,
  mapDispatchToProps
)(DumbContainer);

我这里还有一个游乐场项目https://github.com/vbvxx/playground-reactnative-typescript

【讨论】:

  • 我使用了同样的例子,我发现ThunkResult 是一个误导性的名称。它仍然是一个动作,只是一个异步动作(“thunk”),它不是那个动作的结果。所以RootThunkAction 可能是一个更好的名字。
  • 我认为 ThunkResult 最初是指它指定 asyncActionCreator 期望得到哪种结果的事实。这样 ThunkResult 指定动作创建者返回一个布尔值。
  • 但仅此而已。 testAsyncActionCreator 在此示例中返回一个 thunk,而不是布尔值。 thunk 是一个异步操作,它采用函数的形式。
  • 它返回一个承诺,我同意在大多数情况下它将是 Promise 类型,因为返回某些东西并不是一种常见的行为。然而,可以决定他想在调度一些动作后返回一个布尔值,然后返回类型将是 Promise。所以我认为 ThunkResult 还可以,但这是我的意见:)
猜你喜欢
  • 2016-06-12
  • 2018-10-25
  • 2021-01-01
  • 2020-12-14
  • 2019-03-23
  • 1970-01-01
  • 2020-07-12
  • 2018-07-22
  • 2021-01-20
相关资源
最近更新 更多