clear-react-router 1.8.2 → 1.8.4
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 +16 -12
- package/dist/index.js +33 -68
- package/dist/types.d.ts +2 -4
- package/dist/utils/findRoute.d.ts +1 -1
- package/dist/utils/utils.d.ts +2 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -70,7 +70,7 @@ It provides first-class support for:
|
|
|
70
70
|
|
|
71
71
|
### `createRouter(routes)`
|
|
72
72
|
|
|
73
|
-
Normalizes route configuration
|
|
73
|
+
Normalizes route configuration, extracts dynamic params, builds nested paths.
|
|
74
74
|
|
|
75
75
|
| Property | Type | Description |
|
|
76
76
|
|----------|------|-------------|
|
|
@@ -463,9 +463,7 @@ const UserProfile = () => {
|
|
|
463
463
|
|
|
464
464
|
### `useInvalidate()`
|
|
465
465
|
|
|
466
|
-
Returns a function that revalidates **cached** route data
|
|
467
|
-
|
|
468
|
-
Calling `invalidate()` clears the cached loader result and immediately runs both `beforeLoad` and `loader` for the specified route. This is useful after mutations or any operation that changes data used by the route.
|
|
466
|
+
Returns a function that revalidates **cached** route data. Calling `invalidate()` clears cached route data and immediately runs the corresponding route loader again.
|
|
469
467
|
|
|
470
468
|
#### Current route
|
|
471
469
|
|
|
@@ -490,12 +488,12 @@ await invalidate('/posts');
|
|
|
490
488
|
You can revalidate several routes at once by passing an array of pathnames:
|
|
491
489
|
|
|
492
490
|
```tsx
|
|
493
|
-
await invalidate([
|
|
491
|
+
await invalidate(['/posts', '/profile', '/settings']);
|
|
494
492
|
```
|
|
495
493
|
|
|
496
494
|
#### Dynamic routes
|
|
497
495
|
|
|
498
|
-
When a dynamic route pattern is provided, every cached route
|
|
496
|
+
When a dynamic route pattern is provided, every cached route that matches the pattern will be revalidated.
|
|
499
497
|
|
|
500
498
|
For example:
|
|
501
499
|
|
|
@@ -526,7 +524,7 @@ await invalidate('/posts', { withChildren: true });
|
|
|
526
524
|
await invalidate(['/posts', '/users'], { withChildren: true });
|
|
527
525
|
```
|
|
528
526
|
|
|
529
|
-
This will recursively revalidate cached routes
|
|
527
|
+
This will recursively revalidate all cached child routes.
|
|
530
528
|
|
|
531
529
|
For example, if the following routes have been visited:
|
|
532
530
|
|
|
@@ -550,17 +548,23 @@ will revalidate the cached child routes:
|
|
|
550
548
|
/post/23
|
|
551
549
|
/post/42/comments
|
|
552
550
|
```
|
|
551
|
+
#### Including `beforeLoad`
|
|
552
|
+
|
|
553
|
+
To include the `beforeLoad` function in the revalidation process, pass the `withBeforeLoad` option:
|
|
554
|
+
|
|
555
|
+
```tsx
|
|
556
|
+
await invalidate('/posts', { withBeforeLoad: true });
|
|
557
|
+
await invalidate(['/posts', '/users'], { withBeforeLoad: true });
|
|
558
|
+
```
|
|
559
|
+
|
|
553
560
|
#### Notes
|
|
554
561
|
|
|
555
|
-
* `invalidate()` re-executes both `beforeLoad` and `loader` for the invalidated route.
|
|
556
562
|
* **Only routes that already have cached data are revalidated.**
|
|
557
|
-
* Cached data is
|
|
563
|
+
* Cached data is cleared before the new loader starts.
|
|
558
564
|
* When used as an event handler, wrap the call in an arrow function:
|
|
559
565
|
|
|
560
566
|
```tsx
|
|
561
|
-
<button onClick={() => invalidate()}>
|
|
562
|
-
Refresh
|
|
563
|
-
</button>
|
|
567
|
+
<button onClick={() => invalidate()}>Refresh</button>
|
|
564
568
|
```
|
|
565
569
|
|
|
566
570
|
Passing `invalidate` directly (`onClick={invalidate}`) is not supported because React passes a `MouseEvent` object to event handlers.
|
package/dist/index.js
CHANGED
|
@@ -174,55 +174,38 @@ var createLazyComponent = (importFn, fallback) => {
|
|
|
174
174
|
//#endregion
|
|
175
175
|
//#region utils/utils.ts
|
|
176
176
|
var isLazy = (el) => typeof el.element === "function" && el.element.toString().includes("import(");
|
|
177
|
-
var parseClientRouteItem = (el,
|
|
178
|
-
const
|
|
179
|
-
const staticSegments = [];
|
|
180
|
-
const currentParams = [...parentParams];
|
|
181
|
-
let lastStaticSegment = "";
|
|
182
|
-
for (const segment of segments) if (segment.startsWith(":")) {
|
|
183
|
-
if (!lastStaticSegment) throw new Error(`Route "${el.path}" cannot start with a parameter.`);
|
|
184
|
-
currentParams.push({
|
|
185
|
-
key: lastStaticSegment,
|
|
186
|
-
value: segment.slice(1)
|
|
187
|
-
});
|
|
188
|
-
} else {
|
|
189
|
-
lastStaticSegment = segment;
|
|
190
|
-
staticSegments.push(segment);
|
|
191
|
-
}
|
|
192
|
-
const path = `${parentPath}/${staticSegments.join("/")}`.replace(/\/+/g, "/");
|
|
177
|
+
var parseClientRouteItem = (el, parentPattern = "") => {
|
|
178
|
+
const pattern = `${parentPattern}/${el.path}`.replace(/\/+/g, "/");
|
|
193
179
|
const resolvedElement = isLazy(el) ? createLazyComponent(el.element, el.fallback) : el.element;
|
|
194
180
|
return [{
|
|
195
181
|
...el,
|
|
196
|
-
|
|
197
|
-
params: currentParams,
|
|
182
|
+
pattern,
|
|
198
183
|
element: resolvedElement
|
|
199
|
-
}, ...el.children?.flatMap((child) => parseClientRouteItem(child,
|
|
184
|
+
}, ...el.children?.flatMap((child) => parseClientRouteItem(child, pattern)) ?? []];
|
|
200
185
|
};
|
|
201
|
-
var createRouter = (clientList) => clientList.flatMap((el) => parseClientRouteItem(el
|
|
202
|
-
var getParamsObject = (
|
|
203
|
-
|
|
204
|
-
const
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
}
|
|
186
|
+
var createRouter = (clientList) => clientList.flatMap((el) => parseClientRouteItem(el));
|
|
187
|
+
var getParamsObject = (nextItem, nextPathname) => {
|
|
188
|
+
const { routeItem: stateItem, location: { pathname: statePathname } } = router.state.routeItemDataState.getState();
|
|
189
|
+
const routeItem = nextItem || stateItem;
|
|
190
|
+
const pathname = nextPathname || statePathname;
|
|
191
|
+
if (!routeItem) return {};
|
|
192
|
+
const pathnameSegments = pathname.split("/");
|
|
193
|
+
return routeItem.pattern.split("/").reduce((acc, segment, index) => {
|
|
194
|
+
if (segment.startsWith(":")) acc[segment.slice(1)] = pathnameSegments[index];
|
|
195
|
+
return acc;
|
|
196
|
+
}, {});
|
|
212
197
|
};
|
|
213
198
|
var parseWindowLocation = (location) => ({
|
|
214
199
|
pathname: location.pathname,
|
|
215
200
|
search: location.search
|
|
216
201
|
});
|
|
217
|
-
var comparePaths = (
|
|
218
|
-
|
|
219
|
-
const
|
|
220
|
-
|
|
221
|
-
const splitPathname = pathname.split("/").filter(Boolean);
|
|
222
|
-
return splitElementPath.every((item, index) => item === splitPathname[2 * index]) && splitPathname.length === splitElementPath.length + paramsLength;
|
|
202
|
+
var comparePaths = (route, pathname) => {
|
|
203
|
+
const pattern = route.pattern.split("/").filter(Boolean);
|
|
204
|
+
const current = pathname.split("/").filter(Boolean);
|
|
205
|
+
return pattern.length === current.length ? pattern.every((segment, index) => segment.startsWith(":") || segment === current[index]) : false;
|
|
223
206
|
};
|
|
224
207
|
var findRoute = (pathname, includeAll) => {
|
|
225
|
-
if (includeAll) return routerConfig.routes.find((el) => el.path === "
|
|
208
|
+
if (includeAll) return routerConfig.routes.find((el) => el.path === "*" || comparePaths(el, pathname));
|
|
226
209
|
return routerConfig.routes.find((el) => comparePaths(el, pathname));
|
|
227
210
|
};
|
|
228
211
|
//#endregion
|
|
@@ -241,10 +224,7 @@ var createNavigate = (routerState, revalidateCache) => {
|
|
|
241
224
|
const nextItem = findRoute(location.pathname, true);
|
|
242
225
|
return {
|
|
243
226
|
nextItem,
|
|
244
|
-
params: getParamsObject(
|
|
245
|
-
params: nextItem?.params,
|
|
246
|
-
pathname: location.pathname
|
|
247
|
-
})
|
|
227
|
+
params: getParamsObject(nextItem, location.pathname)
|
|
248
228
|
};
|
|
249
229
|
};
|
|
250
230
|
const beforeLoad = async (routeItem, params) => {
|
|
@@ -323,15 +303,12 @@ var createNavigate = (routerState, revalidateCache) => {
|
|
|
323
303
|
//#region runtime/invalidate.ts
|
|
324
304
|
var redirect = () => Promise.resolve();
|
|
325
305
|
var createInvalidate = ({ routeItemDataState, loaderStateRef, timestampMap, currentLoaderState, contextState }, revalidateCache) => {
|
|
326
|
-
const invalidatePath = async (routeItem, pathname) => {
|
|
306
|
+
const invalidatePath = async (routeItem, pathname, options) => {
|
|
327
307
|
const routePathname = routeItemDataState.getState().location.pathname;
|
|
328
308
|
timestampMap.delete(pathname);
|
|
329
|
-
const params = getParamsObject(
|
|
330
|
-
params: routeItem?.params,
|
|
331
|
-
pathname
|
|
332
|
-
});
|
|
309
|
+
const params = getParamsObject();
|
|
333
310
|
try {
|
|
334
|
-
if (routeItem?.beforeLoad) {
|
|
311
|
+
if (routeItem?.beforeLoad && options?.withBeforeLoad) {
|
|
335
312
|
const context = contextState.getState();
|
|
336
313
|
const setContext = contextState.setState;
|
|
337
314
|
await routeItem.beforeLoad({
|
|
@@ -357,21 +334,21 @@ var createInvalidate = ({ routeItemDataState, loaderStateRef, timestampMap, curr
|
|
|
357
334
|
});
|
|
358
335
|
if (pathname === routePathname) currentLoaderState.setState(loaderStateRef.value);
|
|
359
336
|
};
|
|
360
|
-
const invalidateItem = async (pathname,
|
|
337
|
+
const invalidateItem = async (pathname, options) => {
|
|
361
338
|
const routeItem = findRoute(pathname);
|
|
362
339
|
if (!routeItem) return;
|
|
363
340
|
const pathnameArray = [];
|
|
364
341
|
for (const [key] of timestampMap) if (comparePaths(routeItem, key)) pathnameArray.push(key);
|
|
365
|
-
await Promise.all(pathnameArray.map((pathname) => invalidatePath(routeItem, pathname)));
|
|
366
|
-
if (withChildren && routeItem.children?.length) {
|
|
342
|
+
await Promise.all(pathnameArray.map((pathname) => invalidatePath(routeItem, pathname, options)));
|
|
343
|
+
if (options?.withChildren && routeItem.children?.length) {
|
|
367
344
|
const childPathList = routeItem.children.map((el) => el.path);
|
|
368
|
-
await Promise.all(childPathList.map((el) => invalidateItem(`${pathname}${el}`,
|
|
345
|
+
await Promise.all(childPathList.map((el) => invalidateItem(`${pathname}${el}`, options)));
|
|
369
346
|
}
|
|
370
347
|
};
|
|
371
348
|
return async (pathList, options) => {
|
|
372
349
|
const routePathname = routeItemDataState.getState().location.pathname;
|
|
373
350
|
const pathnameList = Array.isArray(pathList) ? pathList : pathList ? [pathList] : [routePathname];
|
|
374
|
-
await Promise.all(pathnameList.map((pathname) => invalidateItem(pathname, options
|
|
351
|
+
await Promise.all(pathnameList.map((pathname) => invalidateItem(pathname, options)));
|
|
375
352
|
};
|
|
376
353
|
};
|
|
377
354
|
//#endregion
|
|
@@ -423,10 +400,7 @@ var createRevalidateCache = (routerState) => {
|
|
|
423
400
|
try {
|
|
424
401
|
const context = contextState.getState();
|
|
425
402
|
const setContext = contextState.setState;
|
|
426
|
-
const params = getParamsObject(
|
|
427
|
-
params: routeItem.params,
|
|
428
|
-
pathname
|
|
429
|
-
});
|
|
403
|
+
const params = getParamsObject(routeItem, pathname);
|
|
430
404
|
const result = await routeItem?.loader({
|
|
431
405
|
params,
|
|
432
406
|
context,
|
|
@@ -504,13 +478,10 @@ var createRouterInstance = () => {
|
|
|
504
478
|
const invalidate = createInvalidate(routerState, revalidateCache);
|
|
505
479
|
const prefetch = createPrefetch(revalidateCache);
|
|
506
480
|
const useGetAction = (actionKey) => {
|
|
507
|
-
const { routeItem
|
|
481
|
+
const { routeItem } = routerState.routeItemDataState.getState();
|
|
508
482
|
const context = routerState.contextState.getState();
|
|
509
483
|
const setContext = routerState.contextState.setState;
|
|
510
|
-
const params = getParamsObject(
|
|
511
|
-
params: routeItem?.params,
|
|
512
|
-
pathname: location.pathname
|
|
513
|
-
});
|
|
484
|
+
const params = getParamsObject();
|
|
514
485
|
if (!routeItem) throw new Error("Route not found");
|
|
515
486
|
if (!routeItem.actions) throw new Error("Route action creator not found");
|
|
516
487
|
const action = routeItem.actions({
|
|
@@ -549,13 +520,7 @@ var createRouterInstance = () => {
|
|
|
549
520
|
useCurrentLoaderState: () => useGlobalState(routerState.currentLoaderState),
|
|
550
521
|
useScrollMap: () => useGlobalState(routerState.scrollMapState),
|
|
551
522
|
useContextState: () => useGlobalState(routerState.contextState),
|
|
552
|
-
useParams: () =>
|
|
553
|
-
const routeItemData = routerState.routeItemDataState.getState();
|
|
554
|
-
return getParamsObject({
|
|
555
|
-
params: routeItemData.routeItem?.params,
|
|
556
|
-
pathname: routeItemData.location.pathname
|
|
557
|
-
});
|
|
558
|
-
},
|
|
523
|
+
useParams: () => getParamsObject(),
|
|
559
524
|
useNavigate: () => {
|
|
560
525
|
const { blockedRouteState } = routerState;
|
|
561
526
|
const { location } = routerState.routeItemDataState.getState();
|
package/dist/types.d.ts
CHANGED
|
@@ -40,10 +40,7 @@ export type ClientRouteItem = {
|
|
|
40
40
|
};
|
|
41
41
|
export type RouteItem = ClientRouteItem & {
|
|
42
42
|
element: RenderElement;
|
|
43
|
-
|
|
44
|
-
key: string;
|
|
45
|
-
value: string;
|
|
46
|
-
}[];
|
|
43
|
+
pattern: string;
|
|
47
44
|
cacheTimestamp?: number;
|
|
48
45
|
};
|
|
49
46
|
export type Location = {
|
|
@@ -138,6 +135,7 @@ export type RouterType = {
|
|
|
138
135
|
};
|
|
139
136
|
export type InvalidateOptions = {
|
|
140
137
|
withChildren?: boolean;
|
|
138
|
+
withBeforeLoad?: boolean;
|
|
141
139
|
};
|
|
142
140
|
export type RevalidateCache = ({ routeItem, pathname }: RevalidateCacheArgs) => Promise<unknown> | undefined;
|
|
143
141
|
export type Options = Partial<{
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const
|
|
1
|
+
export declare const NOT_FOUND = "*";
|
|
2
2
|
export declare const findRoute: (pathname: string, includeAll?: boolean) => import("..").RouteItem | undefined;
|
package/dist/utils/utils.d.ts
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
import { ClientRouteItem, Location, RouteItem } from '../types';
|
|
2
2
|
export declare const createRouter: (clientList: ClientRouteItem[]) => RouteItem[];
|
|
3
|
-
export declare const getParamsObject: (
|
|
4
|
-
params?: RouteItem["params"];
|
|
5
|
-
pathname: string;
|
|
6
|
-
}) => {};
|
|
3
|
+
export declare const getParamsObject: (nextItem?: RouteItem, nextPathname?: string) => Record<string, string>;
|
|
7
4
|
export declare const parseWindowLocation: (location: typeof window.location) => Location;
|
|
8
|
-
export declare const comparePaths: (
|
|
5
|
+
export declare const comparePaths: (route: RouteItem, pathname: string) => boolean;
|