使用带有类型安全操作和连接的 React 路由器的史诗



我目前正在设置一个侦听类型LOCATION_CHANGELocationChangeAction动作的史诗,这是每当路由器历史记录因路由器操作(例如pushreplace(而更改时触发的操作。

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()运算符?

参数包含索引 0 处具有无效元素的数组,它应该是来自"类型安全操作"的操作创建者实例

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

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
}),
);

除了安德烈的出色回答之外,我想为我的问题提出另一种解决方案。

显式定义"假"操作以从连接的 react-router 镜像 History 操作方法(例如pushreplaceonLocationChanged(的问题在于,当您需要调用/侦听史诗上的操作(例如 redux-observables(时,它将出现进一步的下游问题。

因此,处理此问题的更好方法是在主 RootAction 上为历史记录操作方法添加类型。例如,如果您希望将replace操作添加为ReduxRootAction的一部分,

import { CallHistoryMethodAction, connectRouter, RouterState } from 'connected-react-router';
import { LocationState, Path } from 'history';
const actions = {
userActions,
settingsActions
};
type Replace = (path: Path, state?: LocationState) => CallHistoryMethodAction<[Path, LocationState?]>;
interface RouteActions {
replace: Replace;
}
export type RootAction = ActionType<typeof actions> | ActionType<RouteActions>;
export interface RootState {
router: RouterState;
user: UserState;
settings: SettingsState;
}

这将防止TypeScript/typesafe-actions标记未定义历史记录操作的错误。

最新更新