使用 epics 与 typesafe-actions 和 Connected React Router
Usage of epics with typesafe-actions and Connected React Router
我目前正在设置一个史诗来侦听类型为 LOCATION_CHANGE
或 LocationChangeAction
的动作,该动作会在路由器历史记录因路由器动作(例如 push
或 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()
运算符?
参考
Argument contains array with invalid element at index 0, it should be an action-creator instance from "typesafe-actions"
它可能会抛出该错误,因为 ActionCreator
包含需要 getType?: () => TType
:
的 ActionCreatorTypeMetadata
type TypeConstant = string;
export interface ActionCreatorTypeMetadata<TType extends TypeConstant> {
getType?: () => TType;
}
ActionCreator
export type ActionCreator<T extends { type: string }> = ((
...args: any[]
) => T) &
ActionCreatorTypeMetadata<T['type']>;
但是,onLocationChanged
函数只实现交集的第一部分(returns 一个 object 的函数,它有一个 属性 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;
在你的 epics 上,你可以简单地听取 LOCATION_CHANGE
动作,
const locationEpic: Epic = (action$) => action$.pipe(
filter(isActionOf(RouterActions.onLocationChanged)),
switchMap((epic) => {
// do the rest
}),
);
除了 Andrei 的出色回答外,我还想为我的问题提出一个替代解决方案。
明确定义 'fake' 动作以反映 connected-react-router (such as push
, replace
, onLocationChanged
) is that, it will case further downstream issues when you need to call/listen to the action on your epics (such as redux-observables 中的历史动作方法的问题。
因此,处理此问题的更好方法是在主 RootAction 上添加 History 操作方法的类型。例如,如果您希望将 replace
操作添加为 Redux RootAction
、
的一部分
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
标记您的历史操作未定义的错误。
我目前正在设置一个史诗来侦听类型为 LOCATION_CHANGE
或 LocationChangeAction
的动作,该动作会在路由器历史记录因路由器动作(例如 push
或 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()
运算符?
参考
Argument contains array with invalid element at index 0, it should be an action-creator instance from "typesafe-actions"
它可能会抛出该错误,因为 ActionCreator
包含需要 getType?: () => TType
:
type TypeConstant = string;
export interface ActionCreatorTypeMetadata<TType extends TypeConstant> {
getType?: () => TType;
}
ActionCreator
export type ActionCreator<T extends { type: string }> = ((
...args: any[]
) => T) &
ActionCreatorTypeMetadata<T['type']>;
但是,onLocationChanged
函数只实现交集的第一部分(returns 一个 object 的函数,它有一个 属性 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;
在你的 epics 上,你可以简单地听取 LOCATION_CHANGE
动作,
const locationEpic: Epic = (action$) => action$.pipe(
filter(isActionOf(RouterActions.onLocationChanged)),
switchMap((epic) => {
// do the rest
}),
);
除了 Andrei 的出色回答外,我还想为我的问题提出一个替代解决方案。
明确定义 'fake' 动作以反映 connected-react-router (such as push
, replace
, onLocationChanged
) is that, it will case further downstream issues when you need to call/listen to the action on your epics (such as redux-observables 中的历史动作方法的问题。
因此,处理此问题的更好方法是在主 RootAction 上添加 History 操作方法的类型。例如,如果您希望将 replace
操作添加为 Redux RootAction
、
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
标记您的历史操作未定义的错误。