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 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 { Location } from 'clear-react-router';
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
- }, [context, isCacheItemFresh]);
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
  });
@@ -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
- }) => Promise<unknown> | undefined;
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 & {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clear-react-router",
3
- "version": "1.3.2",
3
+ "version": "1.3.3",
4
4
  "description": "A lightweight, type-safe routing library for React applications",
5
5
  "author": "Andrew Bubnov",
6
6
  "scripts": {