Appearance
状态管理(Recoil)
介绍
在实际的项目开发中,状态管理必不可少,为了方便开发与统一维护,项目集成了Recoil
。
Recoil 说明
Recoil 是 React 的状态管理库,使用 Recoil 会为你创建一个数据流向图,从 atom(共享状态)到 selector(纯函数),再流向 React 组件。Atom 是组件可以订阅的 state 单位。selector 可以同步或异步改变此 state。
Recoil 使用
你可以在 @/store
下创建文件,或者在每个页面目录下创建文件,如下样列:
@/store/user.ts 中定义
import { atom, selector } from 'recoil';
import { queryMessage } from '@/services/user';
import { ResponseData } from '@/utils/request';
export interface CurrentUser {
id: number;
name: string;
avatar: string;
roles: string[];
}
export const initialState: CurrentUser = {
id: 0,
name: '',
avatar: '',
roles: [],
};
export const userState = atom({
key: 'userState',
default: initialState,
});
export const userMessageState = selector({
key: 'userMessageState',
get: async () => {
const response: ResponseData<number> = await queryMessage();
const { data, code } = response;
if (code !== 0) {
throw response.msg;
}
return data || 0;
},
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
@/layouts/UniversalLayout 中使用
import { memo, useEffect, useMemo } from 'react';
import { Outlet, useLocation } from 'react-router-dom';
import classnames from 'classnames';
import { useRecoilValue } from 'recoil';
import { globalState } from '@/store/global';
import { userState } from '@/store/user';
import { useI18n } from '@/store/i18n';
import locales from './locales';
import { formatRoutes, getBreadcrumbRoutes } from '@/utils/router';
import Permission from '@/components/Permission';
import LeftSider from './components/LeftSider';
import RightTop from './components/RightTop';
import RightFooter from './components/RightFooter';
import layoutRotes from './routes';
import useTitle from '@/hooks/useTitle';
import './css/index.less';
export default memo(() => {
const location = useLocation();
const t = useRecoilValue(useI18n(locales));
const global = useRecoilValue(globalState);
const user = useRecoilValue(userState);
// 框架所有菜单路由 与 patch key格式的所有菜单路由
const routerPathKeyRouter = useMemo(() => formatRoutes(layoutRotes), []);
// 当前路由item
const routeItem = useMemo(() => routerPathKeyRouter.pathKeyRouter[location.pathname], [location]);
// 面包屑导航
const breadCrumbs = useMemo(
() =>
getBreadcrumbRoutes(location.pathname, routerPathKeyRouter.pathKeyRouter).map((item) => ({
...item,
title: t(item.title),
})),
[location, routerPathKeyRouter, t],
);
// 设置title
useTitle(t(routeItem?.meta?.title || ''));
useEffect(() => {
console.log('location', location, routeItem);
}, [location]);
return (
<div id='universallayout' className={classnames({ light: global.theme === 'light' })}>
{global.navMode === 'inline' && (
<LeftSider
collapsed={global.collapsed}
userRoles={user.roles}
menuData={routerPathKeyRouter.router}
routeItem={routeItem}
theme={global.theme}
leftSiderFixed={global.leftSiderFixed}
/>
)}
<div id='universallayout-right'>
<RightTop
userRoles={user.roles}
menuData={routerPathKeyRouter.router}
jsonMenuData={routerPathKeyRouter.pathKeyRouter}
routeItem={routeItem}
breadCrumbs={breadCrumbs}
/>
<div id='universallayout-right-main'>
<Permission role={routeItem?.meta?.roles}>
<Outlet />
</Permission>
<RightFooter />
</div>
</div>
</div>
);
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
TIP
详细规则请查看 Recoil 官方文档。