Skip to content

Commit 6cf09f9

Browse files
committed
refactor(packages): @sa/simple-router: stable useRoute
1 parent cfe46ea commit 6cf09f9

File tree

13 files changed

+61
-37
lines changed

13 files changed

+61
-37
lines changed

packages/simple-router/src/Component.tsx

+22-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import { RouterProvider as Provider } from 'react-router-dom';
2+
import { useLayoutEffect, useState } from 'react';
23
import { RouterContext } from './hooks/useRouter';
4+
import { RouteContext } from './hooks/useRoute';
35
import type { Router } from './router';
46

57
export type RouterProviderProps = {
@@ -8,12 +10,28 @@ export type RouterProviderProps = {
810
};
911

1012
const RouterProvider = ({ router, fallback }: RouterProviderProps) => {
13+
const [route, setRoute] = useState(
14+
router.resolve(router.reactRouter.state.location, undefined, router.reactRouter.state.matches.at(-1)?.params)
15+
);
16+
17+
useLayoutEffect(
18+
() =>
19+
router.reactRouter.subscribe(state => {
20+
if (state.navigation.state === 'idle') {
21+
setRoute(router.resolve(state.location, undefined, state.matches.at(-1)?.params));
22+
}
23+
}),
24+
[router, setRoute]
25+
);
26+
1127
return (
1228
<RouterContext.Provider value={router}>
13-
<Provider
14-
fallbackElement={fallback}
15-
router={router.reactRouter}
16-
/>
29+
<RouteContext.Provider value={route}>
30+
<Provider
31+
fallbackElement={fallback}
32+
router={router.reactRouter}
33+
/>
34+
</RouteContext.Provider>
1735
</RouterContext.Provider>
1836
);
1937
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { createContext, useContext } from 'react';
2+
import type { Route } from '../../types';
3+
4+
export const RouteContext = createContext<Route>({} as Route);
5+
export function useRoute() {
6+
const route = useContext(RouteContext);
7+
if (!route) {
8+
throw new Error('useRouter must be used within a Provider');
9+
}
10+
11+
return route;
12+
}

packages/simple-router/src/index.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import { useRouter } from './hooks/useRouter';
2+
import { useRoute } from './hooks/useRoute';
23
import RouterProvider from './Component';
34
import type { RouteRecordNormalized } from './matcher/types';
45

5-
export { useRouter, RouterProvider };
6+
export { useRouter, RouterProvider, useRoute };
67

78
export { createRouter } from './router';
89

packages/simple-router/src/router.ts

+7-19
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,6 @@ export function createRouter({ beforeEach, initRoutes, mode, opt, getReactRoutes
4444

4545
let currentRoute = transformLocationToRoute(reactRouter.state.location, reactRouter.state.matches);
4646

47-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
48-
let listeners: (() => void)[] = [];
49-
5047
reactRouter.getBlocker('beforeGuard', onBeforeRouteChange);
5148

5249
reactRouter.subscribe(afterRouteChange);
@@ -212,9 +209,13 @@ export function createRouter({ beforeEach, initRoutes, mode, opt, getReactRoutes
212209

213210
async function initReady(): Promise<boolean> {
214211
return new Promise((resolved, reject) => {
215-
init(currentRoute.fullPath, blockerOrJump)
216-
.then(() => {
217-
reactRouter.initialize();
212+
init(currentRoute.fullPath)
213+
.then(res => {
214+
if (!res) {
215+
reactRouter.initialize();
216+
} else {
217+
reactRouter.initialize().navigate(resolve(res).fullPath);
218+
}
218219
resolved(true);
219220
})
220221
.catch(e => {
@@ -277,23 +278,12 @@ export function createRouter({ beforeEach, initRoutes, mode, opt, getReactRoutes
277278
return getRoutes().find(route => route.name === key)?.meta;
278279
}
279280

280-
function getSnapshot() {
281-
return currentRoute;
282-
}
283-
284281
function resetRoute() {
285282
// Resets the route matcher so it can begin matching new routes again.
286283
matcher.resetMatcher();
287284
reactRouter._internalSetRoutes(initReactRoutes);
288285
}
289286

290-
function subscribe(listener: () => void) {
291-
listeners = [listener];
292-
return () => {
293-
listeners = [];
294-
};
295-
}
296-
297287
function removeRoute(name: string) {
298288
const matched = matcher.getRecordMatcher(name);
299289
if (!matched) return;
@@ -320,10 +310,8 @@ export function createRouter({ beforeEach, initRoutes, mode, opt, getReactRoutes
320310
removeRoute,
321311
getRouteMetaByKey,
322312
forwardRef,
323-
subscribe,
324313
initReady,
325314
getRoutes,
326-
getSnapshot,
327315
resetRoute,
328316
addReactRoutes,
329317
push,

packages/simple-router/src/types/router.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,6 @@ export type BeforeEach = (
4242
blockerOrJump: NavigationGuardNext
4343
) => boolean;
4444

45-
export type Init = (currentFullPath: string, blockerOrJump: NavigationGuardNext) => Promise<boolean>;
46-
4745
export type AfterEach = (to: RouteLocationNormalizedLoaded, from: RouteLocationNormalizedLoaded) => void;
4846

4947
export type HistoryStateArray = Array<HistoryStateValue>;
@@ -121,3 +119,5 @@ export interface RouteQueryAndHash {
121119
* @internal
122120
*/
123121
export interface RouteLocationNamedRaw extends RouteQueryAndHash, LocationAsRelativeRaw, RouteLocationOptions {}
122+
123+
export type Init = (currentFullPath: string) => Promise<RouteLocationNamedRaw | null>;

packages/simple-router/src/utils/auxi.ts

+4
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ export function removeElement(arr: RouteObject[], name: string | undefined) {
4545
return arr;
4646
}
4747

48+
export function transformLocationToFullPath(location: Location) {
49+
return location.pathname + location.search + location.hash;
50+
}
51+
4852
export function transformLocationToRoute(
4953
location: Location,
5054
match: AgnosticDataRouteMatch[]

src/hooks/common/route.ts

-6
This file was deleted.

src/hooks/common/routerPush.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useRouter } from '@sa/simple-router';
1+
import { useRoute, useRouter } from '@sa/simple-router';
22
import type { RouteKey } from '@elegant-router/types';
33
import type { RouteLocationNamedRaw } from '@sa/simple-router';
44

src/layouts/base-layout/MenuProvider.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { FC, ReactNode } from 'react';
22
import { useMemo } from 'react';
3+
import { useRoute } from '@sa/simple-router';
34
import { getSortRoutes } from '@/store/slice/route';
45
import { selectActiveFirstLevelMenuKey, setActiveFirstLevelMenuKey } from '@/store/slice/tab';
56
import { getActiveFirstLevelMenuKey } from '@/store/slice/tab/shared';

src/layouts/modules/global-header/components/UserAvatar.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { Button, Dropdown } from 'antd';
22
import type { MenuProps } from 'antd';
33
import { useSubmit } from 'react-router-dom';
4+
import { useRoute } from '@sa/simple-router';
45
import { selectToken, selectUserInfo } from '@/store/slice/auth';
56

67
const UserAvatar = memo(() => {

src/layouts/modules/global-tab/index.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import ClassNames from 'classnames';
22
import type BScroll from '@better-scroll/core';
33
import { PageTab } from '@sa/materials';
44
import { useUpdateEffect } from 'ahooks';
5+
import { useRoute } from '@sa/simple-router';
56
import DarkModeContainer from '@/components/stateless/common/DarkModeContainer';
67
import BetterScroll from '@/components/stateless/custom/BetterScroll';
78
import { getDarkMode, getThemeSettings } from '@/store/slice/theme';

src/router/guard/index.ts

+8-3
Original file line numberDiff line numberDiff line change
@@ -15,23 +15,27 @@ import { getRouteHome, initAuthRoute, initConstantRoute } from '@/store/slice/ro
1515
import { getRouteName, getRoutePath } from '@/router/elegant/transform';
1616
import { isStaticSuper, selectUserInfo } from '@/store/slice/auth';
1717

18-
export const init: Init = async (currentFullPath, blockerOrJump) => {
18+
export const init: Init = async currentFullPath => {
1919
await store.dispatch(initConstantRoute());
20+
2021
const isLogin = Boolean(localStg.get('token'));
22+
2123
if (!isLogin) {
2224
const loginRoute: RouteKey = 'login';
2325
const routeHome = getRouteHome(store.getState());
26+
2427
const query = getRouteQueryOfLoginRoute(currentFullPath, routeHome as RouteKey);
2528

2629
const location: RouteLocationNamedRaw = {
2730
name: loginRoute,
2831
query
2932
};
3033

31-
return blockerOrJump(location);
34+
return location;
3235
}
3336
await store.dispatch(initAuthRoute());
34-
return blockerOrJump();
37+
38+
return null;
3539
};
3640

3741
/**
@@ -111,6 +115,7 @@ export const createRouteGuard: BeforeEach = (to, _, blockerOrJump) => {
111115
];
112116

113117
// Find the first matching condition and execute its action
118+
114119
const executeRouteSwitch = routeSwitches.find(({ condition }) => condition)?.callback || blockerOrJump;
115120

116121
return executeRouteSwitch();

src/types/auto-imports.d.ts

-1
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,6 @@ declare global {
164164
const useResetState: typeof import('ahooks')['useResetState']
165165
const useResolvedPath: typeof import('react-router-dom')['useResolvedPath']
166166
const useResponsive: typeof import('ahooks')['useResponsive']
167-
const useRoute: typeof import('../hooks/common/route')['useRoute']
168167
const useRouterPush: typeof import('../hooks/common/routerPush')['useRouterPush']
169168
const useRoutes: typeof import('react-router-dom')['useRoutes']
170169
const useSafeState: typeof import('ahooks')['useSafeState']

0 commit comments

Comments
 (0)