【发布时间】:2020-05-11 01:08:34
【问题描述】:
在我的 react 应用程序中,我喜欢将 redux 实现从 View 逻辑中隐藏在它自己的包“我称之为 sdk 包”中,并且我从 sdk 包中导出 react 的 Hooks 集,以便任何客户端都可以使用它。
简而言之。
const fetch = (params) => (dispatch) => api.get('/media', params);我如何告诉打字稿跳过 thunk 并处理 thunk 函数的返回值 我有一个 Record 对象,如何输入它来跳过中间函数?
上下文
代码:
// hook.tsx
import * as actions from './actions'; // thunks
import * as selectors from './selectors'; // reselect.
import {useSelector, useDispatch} from 'react-redux';
export function useMedia(): [Selectors<typeof selectors>,Actions<typeof actions>] {
// use ref to cache hook
return useRef([
bindSelectors(selectors, useSelector),
bindDispatch(actions, useDispatch()),
]).current;
}
现在在我的视图中,每当我需要使用我使用的媒体切片时。
import { useMedia } from '@sdk/media'
// ....
const [media, mediaActions] = useMedia();
// dispatch an action
mediaActions.fetch({limit:10}).then(console.log);
// select a slice using selector
const photos = media.photosOfAlbum(1);
我的观点不知道/关心 useMedia 是如何工作的,这样我就可以真正在我的代码库中拆分职责,并简化代码共享、测试等。因为随时切换实现而不影响 sdk 的消费者(移动/webapp/甚至 nodejs应用程序)没有人知道 redux 正在为 sdk underhood 提供动力。
问题是我无法正确键入这些钩子..(useMedia)。
所以我们要在这里输入两件事。 bindSelectors 函数和 bindDispatch 函数。
绑定选择器
代码
// @sdk/utils
function bindSelectors <T extends object>(selectors:T, useSelector): CurriedFunctionObject<T>{
return new Proxy(selectors, {
get: (main: T, key: keyof T, ctx: any) => {
const fn = Reflect.get(main, key, ctx);
// always inject store as first prop of fn
// we get store arg from useSelector higher order (its already properly typed)
return (props?: any) => useSelector(store => fn(store, props));
},
}
这个我以前基本上是直接调用选择器对象,因为第一个参数总是存储。
export type CurriedFunctionObject<T> = {
[P in keyof T]: T[P] extends (
s: import('../rootReducer').AppState,
...p: infer Ps
) => infer R
? (...p: Ps) => R
: never;
};
现在我的选择器已经绑定并输入了,我的主要问题是如何编写 Actions 类型..
绑定调度
它的工作原理很像 bindSelectors。我使用“redux-thunk”中的 ActionCreatorsMapObject 来输入它
export function bindDispatch<T extends Record<string, any>>(
obj: T,
dispatch: Dispatch,
): ActionCreatorsMapObject<T> {
return new Proxy(obj, {
get: (main: T, key: keyof T, ctx) => {
const fn = Reflect.get(main, key, ctx);
return (...props: any[]) => dispatch(fn(...props));
},
});
}
bindDispatch 的问题:-
如果我发送一个返回承诺的 thunk,它的类型不正确..
上面的示例代码media.fetch({limit:10}).then///.then is will give errorProperty 'catch' 在类型'(dispatch: any, getState: any, { }: { }) => any'上不存在`
所以基本上因为 fetch 操作看起来像这样
const fetch = (params) => (dispatch) => api.get('/media', params); 所以它需要一个函数(dispatch),那么我如何告诉 typescript 跳过 thunk 并处理 thunk 函数的返回值
【问题讨论】:
标签: javascript reactjs typescript redux