首页 > 解决方案 > 使用带有 typesafe-actions 和 Connected React Router 的史诗

问题描述

我目前正在设置一个监听LOCATION_CHANGEor类型动作的史诗LocationChangeAction,这是每当路由器历史由于路由器动作而发生变化时触发的动作pushor replace

import { LOCATION_CHANGE, LocationChangeAction } from 'connected-react-router';
import { isActionOf } from 'typesafe-actions';

const locationEpic: Epic = (action$) => action$.pipe(
  filter(isActionOf(LocationChangeAction)),
  tap((action) => {
    // do the rest here

  })
);

但是,执行上述操作会引发错误,并且添加typeof似乎也无济于事。

'LocationChangeAction' only refers to a type, but is being used as a value here.

我可以知道使用typesafe-actions 'isActionOf()运算符的正确方法是什么吗?

标签: reactjstypescriptrxjsredux-observabletypesafe-actions

解决方案


参考

参数包含在索引 0 处具有无效元素的数组,它应该是来自“typesafe-actions”的动作创建者实例

它可能会抛出该错误,因为ActionCreator包含ActionCreatorTypeMetadata需要getType?: () => TType

type TypeConstant = string;

export interface ActionCreatorTypeMetadata<TType extends TypeConstant> {
  getType?: () => TType;
}
动作创作者
export type ActionCreator<T extends { type: string }> = ((
  ...args: any[]
) => T) &
  ActionCreatorTypeMetadata<T['type']>;

但是,该onLocationChanged函数仅实现了交集的第一部分(一个返回具有属性的对象的函数type)。

export const LOCATION_CHANGE = '@@router/LOCATION_CHANGE'

export const onLocationChanged = (location, action, isFirstRendering = false) => ({
  type: LOCATION_CHANGE,
  payload: {
    location,
    action,
    isFirstRendering,
  }
})

该函数还必须包含一个属性getType

onLocationChanged.getType = () => `YOUR_TYPE`.

打字稿游乐场


对于那些正在使用的人typesafe-actions,您需要注册LOCATION_CHANGE操作,

import { LOCATION_CHANGE, RouterActionType } from 'connected-react-router';
import { Location } from 'history';
import { createAction } from 'typesafe-actions';

namespace RouterActions {

  export const onLocationChanged = createAction(
    LOCATION_CHANGE,
    (action) => (location: Location, routerAction: RouterActionType, isFirstRendering?: boolean) => action({
      location,
      action: routerAction,
      isFirstRendering,
    }),
  );
}

export default RouterActions;

在你的史诗中,你可以简单地听LOCATION_CHANGE动作,

const locationEpic: Epic = (action$) => action$.pipe(
  filter(isActionOf(RouterActions.onLocationChanged)),
  switchMap((epic) => {
    // do the rest
  }),

);

推荐阅读