Skip to content

Commit a19695b

Browse files
committed
refactor(platform): use rcl-store instead of createGlobalState
1 parent 1630134 commit a19695b

File tree

17 files changed

+125
-105
lines changed

17 files changed

+125
-105
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@
9595
"postcss-html": "^1.5.0",
9696
"postcss-markdown": "^1.2.0",
9797
"prettier": "^2.8.1",
98+
"rcl-store": "^1.0.4",
9899
"react": "^18.2.0",
99100
"react-dom": "^18.2.0",
100101
"react-i18next": "^12.1.1",

packages/hooks/src/createGlobalState.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ interface GlobalStateHook<S> {
1212
setState: Updater<S>;
1313
}
1414

15+
/**
16+
* @deprecated since version 19, try to use `rcl-store`
17+
*/
1518
export function createGlobalState<S>(): GlobalStateHook<S | undefined>;
1619
export function createGlobalState<S>(initialValue: S): GlobalStateHook<S>;
1720
export function createGlobalState<S>(initialValue?: S): GlobalStateHook<S | undefined> {

packages/platform/src/app/App.tsx

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
import type { UserState } from './core/state';
1+
import type { AppUser } from './core/store';
22
import type { DRootProps } from '@react-devui/ui';
33
import type { DLang } from '@react-devui/ui/utils/types';
44

55
import { isNull } from 'lodash';
6+
import { useStore } from 'rcl-store';
67
import React, { useEffect, useMemo, useState } from 'react';
78

89
import { useAsync, useMount, useStorage } from '@react-devui/hooks';
@@ -11,8 +12,7 @@ import { DRoot } from '@react-devui/ui';
1112

1213
import { AppRoutes } from './Routes';
1314
import { STORAGE_KEY } from './config/storage';
14-
import { TOKEN, useHttp, useInit } from './core';
15-
import { useDialogs, useNotifications, useToasts } from './core/state';
15+
import { GlobalStore, TOKEN, useHttp, useInit } from './core';
1616

1717
export type AppTheme = 'light' | 'dark';
1818

@@ -23,9 +23,7 @@ export function App() {
2323
const [loading, setLoading] = useState(!isNull(TOKEN.value));
2424
const languageStorage = useStorage<DLang>(...STORAGE_KEY.language);
2525
const themeStorage = useStorage<AppTheme>(...STORAGE_KEY.theme);
26-
const [dialogs] = useDialogs();
27-
const [notifications] = useNotifications();
28-
const [toasts] = useToasts();
26+
const [{ dialogs, notifications, toasts }] = useStore(GlobalStore, ['dialogs', 'notifications', 'toasts']);
2927

3028
useMount(() => {
3129
if (!isNull(TOKEN.value)) {
@@ -36,7 +34,7 @@ export function App() {
3634
next: (res) => {
3735
TOKEN.set(res);
3836

39-
http<UserState>({
37+
http<AppUser>({
4038
url: '/auth/me',
4139
method: 'get',
4240
}).subscribe({

packages/platform/src/app/core/http/mock.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { DeviceDoc } from '../../utils/types';
2-
import type { UserState, NotificationItem } from '../state';
2+
import type { AppNotification, AppUser } from '../store';
33
import type { JWTToken, JWTTokenPayload } from '../token';
44

55
import axios from 'axios';
@@ -22,16 +22,16 @@ if (environment.http.mock) {
2222
});
2323
};
2424

25-
const admin: UserState = {
25+
const admin: AppUser = {
2626
name: 'admin',
2727
permission: [ROLE_ACL.super_admin],
2828
};
29-
const user: UserState = {
29+
const user: AppUser = {
3030
name: 'user',
3131
avatar: '/assets/imgs/avatar.png',
3232
permission: [0, ROUTES_ACL['/test/acl'], ROUTES_ACL['/test/http']],
3333
};
34-
const notification: NotificationItem[] = [
34+
const notification: AppNotification[] = [
3535
{
3636
id: '1',
3737
title: 'Title1',
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
export { useHttp } from './http';
22
export { TOKEN, useRefreshToken } from './token';
3-
export { useUserState, useNotificationState } from './state';
3+
export { GlobalStore } from './store';
44
export { useACL } from './useACL';
55
export { useInit } from './useInit';
66
export { useMenu } from './useMenu';

packages/platform/src/app/core/state.ts

Lines changed: 0 additions & 26 deletions
This file was deleted.
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import type { DNotificationProps, DToastProps } from '@react-devui/ui';
2+
3+
import { createStore } from 'rcl-store';
4+
5+
export interface AppUser {
6+
name: string;
7+
avatar?: string;
8+
permission: (string | number)[];
9+
}
10+
11+
export interface AppNotification {
12+
id: string;
13+
title: string;
14+
list: {
15+
message: string;
16+
read: boolean;
17+
}[];
18+
}
19+
20+
export interface AppMenu {
21+
expands?: string[];
22+
}
23+
24+
export const GlobalStore = createStore<{
25+
appUser: AppUser;
26+
appNotifications: AppNotification[] | undefined;
27+
appMenu: AppMenu;
28+
notifications: (DNotificationProps & { key: string | number })[];
29+
toasts: (DToastProps & { key: string | number })[];
30+
dialogs: { key: string | number; type: any; props: any }[];
31+
}>({
32+
appUser: {} as any,
33+
appNotifications: undefined,
34+
appMenu: {},
35+
notifications: [],
36+
toasts: [],
37+
dialogs: [],
38+
});

packages/platform/src/app/core/useInit.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,19 @@
1-
import type { UserState, NotificationItem } from './state';
1+
import type { AppNotification, AppUser } from './store';
22

33
import { ROLE_ACL } from '../config/acl';
44
import { useHttp } from './http';
5-
import { useUserState, useNotificationState } from './state';
5+
import { GlobalStore } from './store';
66
import { useRefreshToken } from './token';
77
import { useACL } from './useACL';
8-
import { useMenu } from './useMenu';
98

109
export function useInit() {
1110
const http = useHttp();
1211
const acl = useACL();
1312

1413
const refreshToken = useRefreshToken();
1514

16-
const handleUser = (user: UserState) => {
17-
useUserState.setState(user);
15+
const handleUser = (user: AppUser) => {
16+
GlobalStore.set('appUser', user);
1817

1918
//#region ACL
2019
acl.setFull(user.permission.includes(ROLE_ACL.super_admin));
@@ -23,27 +22,28 @@ export function useInit() {
2322
};
2423

2524
const getNotification = () => {
26-
useNotificationState.setState(undefined);
27-
http<NotificationItem[]>(
25+
GlobalStore.set('appNotifications', undefined);
26+
27+
http<AppNotification[]>(
2828
{
2929
url: '/notification',
3030
method: 'get',
3131
},
3232
{ unmount: false }
3333
).subscribe({
3434
next: (res) => {
35-
useNotificationState.setState(res);
35+
GlobalStore.set('appNotifications', res);
3636
},
3737
});
3838
};
3939

4040
const resetMenu = () => {
41-
useMenu.setState((draft) => {
41+
GlobalStore.set('appMenu', (draft) => {
4242
draft.expands = undefined;
4343
});
4444
};
4545

46-
return (user: UserState) => {
46+
return (user: AppUser) => {
4747
refreshToken();
4848
handleUser(user);
4949
getNotification();

packages/platform/src/app/core/useMenu.ts

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,22 @@ import type { MenuItem } from '../config/menu';
22
import type { DMenuItem } from '@react-devui/ui/components/menu';
33

44
import { isObject, isUndefined } from 'lodash';
5+
import { useStore } from 'rcl-store';
56
import React from 'react';
67
import { useTranslation } from 'react-i18next';
78
import { Link, useLocation } from 'react-router-dom';
89

9-
import { createGlobalState, useMount } from '@react-devui/hooks';
10+
import { useMount } from '@react-devui/hooks';
1011

1112
import { MENU } from '../config/menu';
13+
import { GlobalStore } from './store';
1214
import { useACL } from './useACL';
1315

14-
export interface MenuState {
15-
expands?: string[];
16-
}
17-
const useMenuState = createGlobalState<MenuState>({});
18-
1916
export function useMenu() {
2017
const acl = useACL();
2118
const { t } = useTranslation();
2219
const location = useLocation();
23-
const [menuState, setMenuState] = useMenuState();
20+
const [{ appMenu }, { appMenu: setAppMenu }] = useStore(GlobalStore, ['appMenu']);
2421

2522
const res: {
2623
active?: { path: string; parentSub: MenuItem[] };
@@ -78,8 +75,8 @@ export function useMenu() {
7875
(location.pathname === '/' ? res.firstCanActive?.parentSub : res.active?.parentSub)?.map((item) => item.path);
7976

8077
useMount(() => {
81-
if (isUndefined(menuState.expands)) {
82-
setMenuState((draft) => {
78+
if (isUndefined(appMenu.expands)) {
79+
setAppMenu((draft) => {
8380
draft.expands = getDefaultExpands();
8481
});
8582
}
@@ -90,9 +87,8 @@ export function useMenu() {
9087
menu,
9188
active: location.pathname === '/' ? res.firstCanActive : res.active,
9289
firstCanActive: res.firstCanActive,
93-
expands: menuState.expands ?? getDefaultExpands(),
90+
expands: appMenu.expands ?? getDefaultExpands(),
9491
},
95-
setMenuState,
92+
setAppMenu,
9693
] as const;
9794
}
98-
useMenu.setState = useMenuState.setState;

packages/platform/src/app/routes/layout/header/notification/Notification.tsx

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { DTabsRef } from '@react-devui/ui/components/tabs';
22

33
import { isUndefined } from 'lodash';
4+
import { useStore } from 'rcl-store';
45
import { useRef } from 'react';
56
import { useTranslation } from 'react-i18next';
67

@@ -10,20 +11,20 @@ import { WINDOW_SPACE } from '@react-devui/ui/utils';
1011
import { getClassName } from '@react-devui/utils';
1112

1213
import { AppList } from '../../../../components';
13-
import { useNotificationState } from '../../../../core';
14+
import { GlobalStore } from '../../../../core';
1415

1516
import styles from './Notification.module.scss';
1617

1718
export function AppNotification(props: React.ButtonHTMLAttributes<HTMLButtonElement>): JSX.Element | null {
1819
const tabsRef = useRef<DTabsRef>(null);
1920

20-
const [notification] = useNotificationState();
21+
const [{ appNotifications }] = useStore(GlobalStore, ['appNotifications']);
2122
const { t } = useTranslation();
2223

2324
const num = (() => {
2425
let n = 0;
25-
if (!isUndefined(notification)) {
26-
notification.forEach((notify) => {
26+
if (!isUndefined(appNotifications)) {
27+
appNotifications.forEach((notify) => {
2728
n += notify.list.filter((item) => !item.read).length;
2829
});
2930
}
@@ -33,16 +34,16 @@ export function AppNotification(props: React.ButtonHTMLAttributes<HTMLButtonElem
3334
return (
3435
<DPopover
3536
className={getClassName(styles['app-notification'], {
36-
[styles['app-notification--spinner']]: isUndefined(notification),
37+
[styles['app-notification--spinner']]: isUndefined(appNotifications),
3738
})}
3839
dContent={
39-
isUndefined(notification) ? (
40+
isUndefined(appNotifications) ? (
4041
<LoadingOutlined dTheme="primary" dSize={24} dSpin />
4142
) : (
4243
<>
4344
<DTabs
4445
ref={tabsRef}
45-
dList={notification.map((notify) => ({
46+
dList={appNotifications.map((notify) => ({
4647
id: notify.id,
4748
title: notify.title,
4849
panel: (

0 commit comments

Comments
 (0)