使用带有 typesafe-actions 和 Connected React Router 的史诗
Posted
技术标签:
【中文标题】使用带有 typesafe-actions 和 Connected React Router 的史诗【英文标题】:Usage of epics with typesafe-actions and Connected React Router 【发布时间】:2020-04-12 22:10:50 【问题描述】:我目前正在设置一个侦听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()
运算符?
【问题讨论】:
您能否在问题中添加您的操作定义? 我认为你必须使用onLocationChanged
而不是LocationChangeAction
。 Source
@AndreiGătej 错误不再显示,但现在控制台返回以下错误Argument contains array with invalid element at index 0, it should be an action-creator instance from "typesafe-actions"
。知道如何解决这个问题吗?
【参考方案1】:
除了 Andrei 的出色回答之外,我想提出一个替代解决方案来解决我的问题。
显式定义“假”操作以反映来自connected-react-router(例如push
、replace
、onLocationChanged
)的历史操作方法的问题在于,它会在您需要时解决进一步的下游问题呼叫/聆听您史诗的动作(例如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
标记您的历史操作未定义的错误。
【讨论】:
【参考方案2】:参考
参数包含索引为 0 的无效元素的数组,它应该是来自“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
函数只实现了交集的第一部分(一个返回具有属性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`.
TypeScript Playground
对于使用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
),
);
【讨论】:
知道了!谢谢您的帮助!解决方法是创建一个镜像 LOCATION_CHANGE 的类型安全操作,以便将其识别为有效操作。 很高兴它有帮助!这是一个有趣的问题!:) 你好!感谢您几个月前帮助我!我想我找到了替代解决方案。如果您遇到此问题,您可能需要参考它:) 感谢您告诉我!以上是关于使用带有 typesafe-actions 和 Connected React Router 的史诗的主要内容,如果未能解决你的问题,请参考以下文章
如何使用自动工具编译带有 clang 和选项 -std=c++11 的项目
无法在带有 VS2017 的 Windows 10 上安装和使用 gRPC C/C++