原文链接:https://www.craft.do/s/XQ3SRpQnfAwVHZ,嘻嘻也是自己写的。
以下一切都基于typescript 为起点所写,如果是 js 玩家就不需要看这块。
最近在用 Antd Pro v5,那个简易数据流用起来有点不爽,要自己建立状态管理,状态切片,很是麻烦,相较于以前的dva,更加繁琐。简易是真的只能简易。
所以就想着用回dva,毕竟在这个框架里,用整套的更好。
dva很好用,但是缺少很多的声明,对ts的支持并不是很好,要自己去手动指定类型,而不是自己可以根据上下文推测出来。比如 DefaultState is undefined
比如 connect 的时候,要写一大串的临时声明。
那么我们有没有办法,既能完全拥抱 hooks,也能减少这一块的工作量呢?
有的!
我使用下来发现,包内有 react-redux 的依赖,而且我没有显式安装它,完全的是 Antd Pro v5,或者说是 umi 的内置,统一被导出来了。
import { useSelector } from 'react-redux';
import { useDispatch } from 'umi';
用过 redux 的都知道这俩api,纯纯的hooks啊,再也不需要connect
一大串东西了!
接下来就简单了,我们整理一下大概的思路:
- 定义 models 的切片(就是按业务角色分命名空间)。
每个切片内自维护声明属于自己这一部分的类型。
state 的类型需要额外导出。
- 新建个文件夹,可以叫
apps
,其中新建index.ts
,主要就是重写上面提及的俩hooks。 - 最后在页面里面使用,可以得到完整的提示。
第一步:新建models(状态切片)
import type { Effect, Reducer } from 'umi';
export interface UsersSliceState {
userList: UserType[];
currentUser: UserType;
}
interface UsersSliceType {
namespace: 'users';
state: UsersSliceState;
effects: {
fetchUsers: Effect;
};
reducers: {
save: Reducer<UsersSliceState>;
warn: Reducer<UsersSliceState>;
};
}
const UsersSlice: UsersSliceType = {
// 跟着类型写就完事儿
}
第二步、src下新建 apps 文件夹,并新建 index.ts 以重写hooks
import type { TypedUseSelectorHook } from 'react-redux';
import { useSelector } from 'react-redux';
import { getDvaApp, useDispatch } from 'umi';
import type { UsersSliceState } from 'umi';
// 这里本来就没有类型提示,很烦,需要自己声明!
// 如果 _store有类型,那就皆大欢喜,可惜是any,所以对我们没有帮助。
export const _store = getDvaApp()._store;
export type _RootState = ReturnType<typeof _store.getState>;
// 重声明根节点的类型,使其可以显式接受类型
export type RootState = {
users: UsersSliceState;
};
// 重写并导出
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
export const useAppDispatch = useDispatch;
第三步、页面内使用
import { useAppDispatch, useAppSelector } from '@/apps';
export default function () {
// 获取到想要的数据
const { currentUser } = useAppSelector((s) => s.users);
useEffect(() => {
// 发起 action
dispatch({ type: 'users/fetchUsers' });
}, [dispatch]);
return <></>
}
至此,我们已经可以完整体验hooks的便捷了,后续只要在 apps那个文件内加入自己注册后的状态分支即可。
如果觉得有帮助,希望不吝给个赞!