clear-react-router 1.3.2 → 1.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -6
- package/dist/hooks/useHandleNavigation.d.ts +3 -1
- package/dist/hooks/useLoader.d.ts +3 -1
- package/dist/index.js +27 -17
- package/dist/types/global.d.ts +5 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -26,9 +26,9 @@ Normalizes route configuration. Handles wildcard `*` routes, extracts dynamic pa
|
|
|
26
26
|
|----------|------|-------------|
|
|
27
27
|
| `path` | `string` | Route path, e.g., `/user/:userId` |
|
|
28
28
|
| `element` | `ReactElement \| () => ReactElement \| LazyComponent` | Component to render |
|
|
29
|
-
| `loader` | `({ params, context }) => Promise<unknown>` | Fetch data using route params and context |
|
|
30
|
-
| `beforeLoad` | `({ params, context, redirect }) => Promise<unknown> \| undefined` | Auth checks and redirects. `redirect` is provided by the router |
|
|
31
|
-
| `afterLoad` | `({ params, context }) => Promise<void>` | Analytics, side effects after data is loaded |
|
|
29
|
+
| `loader` | `({ params, context, setContext }) => Promise<unknown>` | Fetch data using route params and context. Can update context via `setContext` |
|
|
30
|
+
| `beforeLoad` | `({ params, context, redirect, setContext }) => Promise<unknown> \| undefined \| void` | Auth checks and redirects. Can update context via `setContext`. `redirect` is provided by the router |
|
|
31
|
+
| `afterLoad` | `({ params, context, setContext }) => Promise<void>` | Analytics, side effects after data is loaded. Can update context via `setContext` |
|
|
32
32
|
| `fallback` | `ReactElement \| () => ReactElement` | Loading fallback (for lazy loading) |
|
|
33
33
|
| `loaderFallback` | `ReactElement \| () => ReactElement` | Loading fallback (for loader) |
|
|
34
34
|
| `errorElement` | `ReactElement \| () => ReactElement` | Error fallback |
|
|
@@ -95,7 +95,7 @@ Function provided to `beforeLoad` for programmatic redirection.
|
|
|
95
95
|
**Type:** `(arg: Location | string) => Promise<void>`
|
|
96
96
|
|
|
97
97
|
```
|
|
98
|
-
import type {
|
|
98
|
+
import type { createRouter } from 'clear-react-router';
|
|
99
99
|
|
|
100
100
|
const routes = createRouter([
|
|
101
101
|
{
|
|
@@ -107,8 +107,6 @@ const routes = createRouter([
|
|
|
107
107
|
},
|
|
108
108
|
]);
|
|
109
109
|
|
|
110
|
-
or
|
|
111
|
-
|
|
112
110
|
const routes = createRouter([
|
|
113
111
|
{
|
|
114
112
|
path: '/dashboard',
|
|
@@ -118,6 +116,21 @@ const routes = createRouter([
|
|
|
118
116
|
},
|
|
119
117
|
},
|
|
120
118
|
]);
|
|
119
|
+
|
|
120
|
+
const routes = createRouter([
|
|
121
|
+
{
|
|
122
|
+
path: '/user/:userId',
|
|
123
|
+
loader: async ({ params, context, setContext }) => {
|
|
124
|
+
const user = await fetchUser(params.userId);
|
|
125
|
+
setContext({ ...context, currentUser: user });
|
|
126
|
+
return { user };
|
|
127
|
+
},
|
|
128
|
+
beforeLoad: async ({ context, setContext, redirect }) => {
|
|
129
|
+
if (!context.token) return redirect('/login');
|
|
130
|
+
setContext({ ...context, lastVisit: Date.now() });
|
|
131
|
+
},
|
|
132
|
+
}
|
|
133
|
+
]);
|
|
121
134
|
|
|
122
135
|
```
|
|
123
136
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type Dispatch, type SetStateAction } from 'react';
|
|
1
2
|
import type { BlockerState, Location, RevalidateCacheArgs, RouteItem, UpdateBlockedRouteProps } from '../types/global';
|
|
2
3
|
type UseHandleNavigation = {
|
|
3
4
|
routeList: RouteItem[];
|
|
@@ -5,8 +6,9 @@ type UseHandleNavigation = {
|
|
|
5
6
|
context: Record<string, unknown>;
|
|
6
7
|
revalidateCache(arg: RevalidateCacheArgs): Promise<void>;
|
|
7
8
|
isAnimated: boolean;
|
|
9
|
+
setContext: Dispatch<SetStateAction<Record<string, unknown>>>;
|
|
8
10
|
};
|
|
9
|
-
export declare const useHandleNavigation: ({ setLocation, routeList, context, revalidateCache, isAnimated, }: UseHandleNavigation) => {
|
|
11
|
+
export declare const useHandleNavigation: ({ setLocation, routeList, context, revalidateCache, isAnimated, setContext, }: UseHandleNavigation) => {
|
|
10
12
|
blockerState: BlockerState;
|
|
11
13
|
updateLocation: (nextLocation: Location) => Promise<void>;
|
|
12
14
|
updateBlockedRoute: ({ type, payload }: UpdateBlockedRouteProps) => void;
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import { type Dispatch, type SetStateAction } from 'react';
|
|
1
2
|
import type { RevalidateCacheArgs, RouteItem } from '../types/global';
|
|
2
3
|
type UseLoaderParams = {
|
|
3
4
|
routeList: RouteItem[];
|
|
4
5
|
context: Record<string, unknown>;
|
|
6
|
+
setContext: Dispatch<SetStateAction<Record<string, unknown>>>;
|
|
5
7
|
};
|
|
6
|
-
export declare const useLoader: ({ routeList, context }: UseLoaderParams) => {
|
|
8
|
+
export declare const useLoader: ({ routeList, context, setContext }: UseLoaderParams) => {
|
|
7
9
|
loaderCache: unknown;
|
|
8
10
|
loaderError: boolean;
|
|
9
11
|
prefetchLoader: (pathname: string) => Promise<void>;
|
package/dist/index.js
CHANGED
|
@@ -77,6 +77,15 @@ var Provider = ({ children, setContext, context, updateBlockedRoute, updateLocat
|
|
|
77
77
|
});
|
|
78
78
|
};
|
|
79
79
|
//#endregion
|
|
80
|
+
//#region hooks/useLatest.ts
|
|
81
|
+
var useLatest = (value) => {
|
|
82
|
+
const ref = useRef(value);
|
|
83
|
+
useEffect(() => {
|
|
84
|
+
ref.current = value;
|
|
85
|
+
}, [value]);
|
|
86
|
+
return ref;
|
|
87
|
+
};
|
|
88
|
+
//#endregion
|
|
80
89
|
//#region utils/createLazyComponent.tsx
|
|
81
90
|
var createLazyComponent = (importFn, fallback) => {
|
|
82
91
|
const LazyComp = lazy(() => importFn().then((module) => ({ default: module.default || module })));
|
|
@@ -128,17 +137,8 @@ var comparePaths = (el, pathname) => {
|
|
|
128
137
|
return splitElementPath.every((item, index) => item === splitPathname[index + (index ? 1 : 0)]) && splitPathname.length === splitElementPath.length + paramsLength;
|
|
129
138
|
};
|
|
130
139
|
//#endregion
|
|
131
|
-
//#region hooks/useLatest.ts
|
|
132
|
-
var useLatest = (value) => {
|
|
133
|
-
const ref = useRef(value);
|
|
134
|
-
useEffect(() => {
|
|
135
|
-
ref.current = value;
|
|
136
|
-
}, [value]);
|
|
137
|
-
return ref;
|
|
138
|
-
};
|
|
139
|
-
//#endregion
|
|
140
140
|
//#region hooks/useHandleNavigation.ts
|
|
141
|
-
var useHandleNavigation = ({ setLocation, routeList, context, revalidateCache, isAnimated }) => {
|
|
141
|
+
var useHandleNavigation = ({ setLocation, routeList, context, revalidateCache, isAnimated, setContext }) => {
|
|
142
142
|
const [blockedRoute, setBlockedRoute] = useState({
|
|
143
143
|
from: "",
|
|
144
144
|
to: ""
|
|
@@ -174,7 +174,8 @@ var useHandleNavigation = ({ setLocation, routeList, context, revalidateCache, i
|
|
|
174
174
|
await nextItem.beforeLoad({
|
|
175
175
|
context,
|
|
176
176
|
redirect,
|
|
177
|
-
params
|
|
177
|
+
params,
|
|
178
|
+
setContext
|
|
178
179
|
});
|
|
179
180
|
} catch {
|
|
180
181
|
setBeforeLoadError(true);
|
|
@@ -199,14 +200,16 @@ var useHandleNavigation = ({ setLocation, routeList, context, revalidateCache, i
|
|
|
199
200
|
setBeforeLoadError(false);
|
|
200
201
|
if (nextItem?.afterLoad) await nextItem.afterLoad({
|
|
201
202
|
context,
|
|
202
|
-
params
|
|
203
|
+
params,
|
|
204
|
+
setContext
|
|
203
205
|
});
|
|
204
206
|
}, [
|
|
205
207
|
context,
|
|
206
208
|
revalidateCache,
|
|
207
209
|
routeList,
|
|
208
210
|
transitionedNavigation,
|
|
209
|
-
isAnimated
|
|
211
|
+
isAnimated,
|
|
212
|
+
setContext
|
|
210
213
|
]);
|
|
211
214
|
const setNextLocationRef = useLatest(navigationHandler);
|
|
212
215
|
const updateBlockedRoute = useCallback(({ type, payload = "" }) => setBlockedRoute((prevState) => {
|
|
@@ -265,7 +268,7 @@ var useHandleNavigation = ({ setLocation, routeList, context, revalidateCache, i
|
|
|
265
268
|
};
|
|
266
269
|
//#endregion
|
|
267
270
|
//#region hooks/useLoader.ts
|
|
268
|
-
var useLoader = ({ routeList, context }) => {
|
|
271
|
+
var useLoader = ({ routeList, context, setContext }) => {
|
|
269
272
|
const [loaderCache, setLoaderCache] = useState();
|
|
270
273
|
const [loaderError, setLoaderError] = useState(false);
|
|
271
274
|
const [isLoading, setIsLoading] = useState(false);
|
|
@@ -301,7 +304,8 @@ var useLoader = ({ routeList, context }) => {
|
|
|
301
304
|
});
|
|
302
305
|
const result = await routeItem?.loader({
|
|
303
306
|
params,
|
|
304
|
-
context
|
|
307
|
+
context,
|
|
308
|
+
setContext
|
|
305
309
|
});
|
|
306
310
|
cacheTimestampsRef.current = {
|
|
307
311
|
...cacheTimestampsRef.current,
|
|
@@ -317,7 +321,11 @@ var useLoader = ({ routeList, context }) => {
|
|
|
317
321
|
} finally {
|
|
318
322
|
if (isCurrentRoute) setIsLoading(false);
|
|
319
323
|
}
|
|
320
|
-
}, [
|
|
324
|
+
}, [
|
|
325
|
+
context,
|
|
326
|
+
isCacheItemFresh,
|
|
327
|
+
setContext
|
|
328
|
+
]);
|
|
321
329
|
return {
|
|
322
330
|
loaderCache,
|
|
323
331
|
loaderError,
|
|
@@ -377,12 +385,14 @@ var RouterProvider = ({ children, routeList, context: initialContext = {}, isAni
|
|
|
377
385
|
useApplyCustomAnimation(animationDuration);
|
|
378
386
|
const { loaderError, loaderCache, prefetchLoader, revalidateCache, isLoading } = useLoader({
|
|
379
387
|
routeList,
|
|
380
|
-
context
|
|
388
|
+
context,
|
|
389
|
+
setContext
|
|
381
390
|
});
|
|
382
391
|
const { blockerState, updateLocation, updateBlockedRoute, beforeLoadError } = useHandleNavigation({
|
|
383
392
|
setLocation,
|
|
384
393
|
routeList,
|
|
385
394
|
context,
|
|
395
|
+
setContext,
|
|
386
396
|
revalidateCache,
|
|
387
397
|
isAnimated
|
|
388
398
|
});
|
package/dist/types/global.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ComponentType, ReactElement } from 'react';
|
|
1
|
+
import type { ComponentType, Dispatch, ReactElement, SetStateAction } from 'react';
|
|
2
2
|
export type LazyComponent = () => Promise<{
|
|
3
3
|
default: ComponentType<unknown>;
|
|
4
4
|
}>;
|
|
@@ -8,6 +8,7 @@ export type ClientRouteItem = {
|
|
|
8
8
|
loader?(arg: {
|
|
9
9
|
params: Record<string, string>;
|
|
10
10
|
context: Record<string, unknown>;
|
|
11
|
+
setContext: Dispatch<SetStateAction<Record<string, unknown>>>;
|
|
11
12
|
}): Promise<unknown>;
|
|
12
13
|
loaderFallback?: (() => ReactElement) | ReactElement;
|
|
13
14
|
errorElement?: (() => ReactElement) | ReactElement;
|
|
@@ -18,10 +19,12 @@ export type ClientRouteItem = {
|
|
|
18
19
|
context: Record<string, unknown>;
|
|
19
20
|
redirect: (arg: Location | string) => Promise<void>;
|
|
20
21
|
params: Record<string, string>;
|
|
21
|
-
|
|
22
|
+
setContext: Dispatch<SetStateAction<Record<string, unknown>>>;
|
|
23
|
+
}) => Promise<unknown> | undefined | void;
|
|
22
24
|
afterLoad?: (arg: {
|
|
23
25
|
context: Record<string, unknown>;
|
|
24
26
|
params: Record<string, string>;
|
|
27
|
+
setContext: Dispatch<SetStateAction<Record<string, unknown>>>;
|
|
25
28
|
}) => Promise<void>;
|
|
26
29
|
};
|
|
27
30
|
export type RouteItem = ClientRouteItem & {
|