clear-react-router 1.8.5 → 1.8.7
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 +9 -1
- package/dist/components/Link.d.ts +8 -10
- package/dist/hooks/useInvalidate.d.ts +1 -1
- package/dist/index.js +49 -25
- package/dist/runtime/invalidate.d.ts +2 -2
- package/dist/types.d.ts +14 -4
- package/dist/utils/createLazyComponent.d.ts +6 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -88,7 +88,7 @@ Normalizes route configuration. Extracts dynamic params, builds nested paths.
|
|
|
88
88
|
|
|
89
89
|
### `Link`
|
|
90
90
|
|
|
91
|
-
Component for client-side navigation with prefetch support, active state detection, and pending state styling.
|
|
91
|
+
Component for client-side navigation with prefetch support, active state detection, and pending state styling. Prefetch includes lazy route component preload.
|
|
92
92
|
|
|
93
93
|
| Prop | Type | Default | Description |
|
|
94
94
|
|------|------|---------|-------------|
|
|
@@ -584,6 +584,14 @@ await invalidate('/posts', { withBeforeLoad: true });
|
|
|
584
584
|
await invalidate(['/posts', '/users'], { withBeforeLoad: true });
|
|
585
585
|
```
|
|
586
586
|
|
|
587
|
+
#### Returns
|
|
588
|
+
|
|
589
|
+
An array of objects with the following structure:
|
|
590
|
+
```ts
|
|
591
|
+
{ path: string; data: unknown; error: unknown }
|
|
592
|
+
```
|
|
593
|
+
Each object represents a revalidated route, where `path` is the route pathname, `data` is the revalidated loader result, and `error` is the loader error, if any.
|
|
594
|
+
|
|
587
595
|
#### Notes
|
|
588
596
|
|
|
589
597
|
* **Only routes that already have cached data are revalidated.**
|
|
@@ -1,18 +1,16 @@
|
|
|
1
|
-
import { type CSSProperties, ReactNode } from 'react';
|
|
1
|
+
import { type CSSProperties, ReactNode, ComponentPropsWithoutRef } from 'react';
|
|
2
2
|
import { RouterProps } from '../types';
|
|
3
|
-
type
|
|
3
|
+
type States = {
|
|
4
|
+
isActive: boolean;
|
|
5
|
+
isPending: boolean;
|
|
6
|
+
};
|
|
7
|
+
type LinkProps = Omit<ComponentPropsWithoutRef<'a'>, 'href' | 'className' | 'style'> & {
|
|
4
8
|
to: string;
|
|
5
9
|
children: ReactNode;
|
|
6
10
|
prefetch?: RouterProps['prefetch'];
|
|
7
11
|
hoverPrefetchDelay?: number;
|
|
8
|
-
style?: CSSProperties | ((
|
|
9
|
-
|
|
10
|
-
isPending: boolean;
|
|
11
|
-
}) => CSSProperties);
|
|
12
|
-
className?: string | (({ isActive }: {
|
|
13
|
-
isActive: boolean;
|
|
14
|
-
isPending: boolean;
|
|
15
|
-
}) => string);
|
|
12
|
+
style?: CSSProperties | ((arg: States) => CSSProperties);
|
|
13
|
+
className?: string | ((arg: States) => string);
|
|
16
14
|
activeClassName?: string;
|
|
17
15
|
pendingClassName?: string;
|
|
18
16
|
onClick?(): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const useInvalidate: () => (pathList?: string | string[], options?: import("../types").InvalidateOptions) => Promise<
|
|
1
|
+
export declare const useInvalidate: () => (pathList?: string | string[], options?: import("../types").InvalidateOptions) => Promise<import("../types").InvalidateResult[]>;
|
package/dist/index.js
CHANGED
|
@@ -165,22 +165,29 @@ var import_jsx_runtime = (/* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
165
165
|
module.exports = require_react_jsx_runtime_production();
|
|
166
166
|
})))();
|
|
167
167
|
var createLazyComponent = (importFn, fallback) => {
|
|
168
|
-
const
|
|
169
|
-
|
|
168
|
+
const load = () => importFn().then((module) => ({ default: module.default || module }));
|
|
169
|
+
const LazyComp = lazy(load);
|
|
170
|
+
const Component = () => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Suspense, {
|
|
170
171
|
fallback: typeof fallback === "function" ? fallback() : fallback || null,
|
|
171
172
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LazyComp, {})
|
|
172
173
|
});
|
|
174
|
+
return {
|
|
175
|
+
Component,
|
|
176
|
+
preloadElement: load
|
|
177
|
+
};
|
|
173
178
|
};
|
|
174
179
|
//#endregion
|
|
175
180
|
//#region utils/utils.ts
|
|
176
181
|
var isLazy = (el) => typeof el.element === "function" && el.element.toString().includes("import(");
|
|
177
182
|
var parseClientRouteItem = (el, parentPattern = "") => {
|
|
178
183
|
const pattern = `${parentPattern}/${el.path}`.replace(/\/+/g, "/");
|
|
179
|
-
const
|
|
184
|
+
const preloadElement = isLazy(el) ? createLazyComponent(el.element, el.fallback).preloadElement : void 0;
|
|
185
|
+
const resolvedElement = isLazy(el) ? createLazyComponent(el.element, el.fallback).Component : el.element;
|
|
180
186
|
return [{
|
|
181
187
|
...el,
|
|
182
188
|
pattern,
|
|
183
|
-
element: resolvedElement
|
|
189
|
+
element: resolvedElement,
|
|
190
|
+
preloadElement
|
|
184
191
|
}, ...el.children?.flatMap((child) => parseClientRouteItem(child, pattern)) ?? []];
|
|
185
192
|
};
|
|
186
193
|
var createRouter = (clientList) => clientList.flatMap((el) => parseClientRouteItem(el));
|
|
@@ -330,37 +337,43 @@ var createInvalidate = ({ routeItemDataState, loaderStateRef, timestampMap, curr
|
|
|
330
337
|
beforeLoadError: error
|
|
331
338
|
}));
|
|
332
339
|
}
|
|
333
|
-
await revalidateCache({
|
|
340
|
+
const result = await revalidateCache({
|
|
334
341
|
routeItem,
|
|
335
342
|
pathname
|
|
336
343
|
});
|
|
337
344
|
if (pathname === routePathname) currentLoaderState.setState(loaderStateRef.value);
|
|
345
|
+
return {
|
|
346
|
+
path: pathname,
|
|
347
|
+
...result
|
|
348
|
+
};
|
|
338
349
|
};
|
|
339
350
|
const invalidateItem = async (pathname, options) => {
|
|
340
351
|
const routeItem = findRoute(pathname);
|
|
341
|
-
if (!routeItem) return;
|
|
352
|
+
if (!routeItem) return [];
|
|
342
353
|
const pathnameArray = [];
|
|
343
354
|
for (const [key] of timestampMap) if (comparePaths(routeItem, key)) pathnameArray.push(key);
|
|
344
|
-
await Promise.all(pathnameArray.map((pathname) => invalidatePath(routeItem, pathname, options)));
|
|
345
|
-
if (options?.withChildren
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
}
|
|
355
|
+
const currentResults = await Promise.all(pathnameArray.map((pathname) => invalidatePath(routeItem, pathname, options)));
|
|
356
|
+
if (!options?.withChildren || !routeItem.children?.length) return currentResults;
|
|
357
|
+
const childResults = await Promise.all(routeItem.children.map((child) => invalidateItem(`${pathname}${child.path}`, options)));
|
|
358
|
+
return [...currentResults, ...childResults.flat()];
|
|
349
359
|
};
|
|
350
360
|
return async (pathList, options) => {
|
|
351
361
|
const routePathname = routeItemDataState.getState().location.pathname;
|
|
352
362
|
const pathnameList = Array.isArray(pathList) ? pathList : pathList ? [pathList] : [routePathname];
|
|
353
|
-
await Promise.all(pathnameList.map((pathname) => invalidateItem(pathname, options)));
|
|
363
|
+
return (await Promise.all(pathnameList.map((pathname) => invalidateItem(pathname, options)))).flat();
|
|
354
364
|
};
|
|
355
365
|
};
|
|
356
366
|
//#endregion
|
|
357
367
|
//#region runtime/prefetch.ts
|
|
358
368
|
var createPrefetch = (revalidateCache) => async (pathname) => {
|
|
359
369
|
const item = findRoute(pathname);
|
|
360
|
-
if (item)
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
370
|
+
if (item) {
|
|
371
|
+
await item.preloadElement?.();
|
|
372
|
+
await revalidateCache({
|
|
373
|
+
routeItem: item,
|
|
374
|
+
pathname
|
|
375
|
+
});
|
|
376
|
+
}
|
|
364
377
|
};
|
|
365
378
|
//#endregion
|
|
366
379
|
//#region utils/revalidateCache.ts
|
|
@@ -393,10 +406,7 @@ var createRevalidateCache = (routerState) => {
|
|
|
393
406
|
if (isCacheItemFresh({
|
|
394
407
|
routeItem,
|
|
395
408
|
pathname
|
|
396
|
-
}))
|
|
397
|
-
loaderStateRef.set(loaderMapRef[pathname]);
|
|
398
|
-
return;
|
|
399
|
-
}
|
|
409
|
+
})) loaderStateRef.set(loaderMapRef[pathname]);
|
|
400
410
|
const promise = (async () => {
|
|
401
411
|
if (!routeItem?.loader) return;
|
|
402
412
|
try {
|
|
@@ -415,6 +425,10 @@ var createRevalidateCache = (routerState) => {
|
|
|
415
425
|
loaderError: null
|
|
416
426
|
}));
|
|
417
427
|
loaderMapRef[pathname] = loaderStateRef.value;
|
|
428
|
+
return {
|
|
429
|
+
data: result,
|
|
430
|
+
error: null
|
|
431
|
+
};
|
|
418
432
|
} catch (error) {
|
|
419
433
|
const retry = getRetry(routeItem);
|
|
420
434
|
if (retry && retry.count > retried) {
|
|
@@ -424,11 +438,21 @@ var createRevalidateCache = (routerState) => {
|
|
|
424
438
|
routeItem,
|
|
425
439
|
pathname
|
|
426
440
|
}, retried + 1);
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
}
|
|
441
|
+
return {
|
|
442
|
+
data: null,
|
|
443
|
+
error
|
|
444
|
+
};
|
|
445
|
+
} else {
|
|
446
|
+
loaderStateRef.set((prev) => ({
|
|
447
|
+
...prev,
|
|
448
|
+
data: null,
|
|
449
|
+
loaderError: error
|
|
450
|
+
}));
|
|
451
|
+
return {
|
|
452
|
+
data: null,
|
|
453
|
+
error
|
|
454
|
+
};
|
|
455
|
+
}
|
|
432
456
|
} finally {
|
|
433
457
|
loadingPromises.delete(pathname);
|
|
434
458
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { type InvalidateOptions, RevalidateCache, RouterState } from '../types';
|
|
2
|
-
export declare const createInvalidate: ({ routeItemDataState, loaderStateRef, timestampMap, currentLoaderState, contextState }: RouterState, revalidateCache: RevalidateCache) => (pathList?: string | string[], options?: InvalidateOptions) => Promise<
|
|
1
|
+
import { type InvalidateOptions, InvalidateResult, RevalidateCache, RouterState } from '../types';
|
|
2
|
+
export declare const createInvalidate: ({ routeItemDataState, loaderStateRef, timestampMap, currentLoaderState, contextState }: RouterState, revalidateCache: RevalidateCache) => (pathList?: string | string[], options?: InvalidateOptions) => Promise<InvalidateResult[]>;
|
package/dist/types.d.ts
CHANGED
|
@@ -34,7 +34,7 @@ export type ClientRouteItem = {
|
|
|
34
34
|
actions?: (arg: {
|
|
35
35
|
context: Record<string, unknown>;
|
|
36
36
|
params: Record<string, string>;
|
|
37
|
-
invalidate: (path?: string) => Promise<
|
|
37
|
+
invalidate: (path?: string) => Promise<InvalidateResult[]>;
|
|
38
38
|
setContext: Dispatch<SetStateAction<Record<string, unknown>>>;
|
|
39
39
|
}) => Record<string, (arg: FormData) => Promise<unknown> | Promise<void> | void | unknown>;
|
|
40
40
|
};
|
|
@@ -42,6 +42,9 @@ export type RouteItem = ClientRouteItem & {
|
|
|
42
42
|
element: RenderElement;
|
|
43
43
|
pattern: string;
|
|
44
44
|
cacheTimestamp?: number;
|
|
45
|
+
preloadElement?(): Promise<{
|
|
46
|
+
default: ComponentType<unknown>;
|
|
47
|
+
}>;
|
|
45
48
|
};
|
|
46
49
|
export type Location = {
|
|
47
50
|
pathname: string;
|
|
@@ -110,7 +113,7 @@ export type RouterType = {
|
|
|
110
113
|
state: Omit<RouterState, 'loaderStateRef' | 'timestampMap'>;
|
|
111
114
|
runtime: {
|
|
112
115
|
navigate(arg: Location): Promise<void>;
|
|
113
|
-
invalidate(pathList?: string | string[], options?: InvalidateOptions): Promise<
|
|
116
|
+
invalidate(pathList?: string | string[], options?: InvalidateOptions): Promise<InvalidateResult[]>;
|
|
114
117
|
prefetch(pathname: string): Promise<void>;
|
|
115
118
|
};
|
|
116
119
|
hooks: {
|
|
@@ -128,7 +131,7 @@ export type RouterType = {
|
|
|
128
131
|
useNavigate: () => (arg: Location | string | -1) => Promise<void>;
|
|
129
132
|
useGetAction: (actionKey: string) => {
|
|
130
133
|
currentAction: (arg: FormData) => Promise<unknown> | Promise<void> | void | unknown;
|
|
131
|
-
invalidate: (pathList?: string | string[], options?: InvalidateOptions) => Promise<
|
|
134
|
+
invalidate: (pathList?: string | string[], options?: InvalidateOptions) => Promise<InvalidateResult[]>;
|
|
132
135
|
};
|
|
133
136
|
useRestoreScroll: () => () => void;
|
|
134
137
|
useAction: (action: string, options?: Options) => (arg: FormData) => Promise<void>;
|
|
@@ -138,9 +141,16 @@ export type InvalidateOptions = {
|
|
|
138
141
|
withChildren?: boolean;
|
|
139
142
|
withBeforeLoad?: boolean;
|
|
140
143
|
};
|
|
141
|
-
export type RevalidateCache = ({ routeItem, pathname }: RevalidateCacheArgs) => Promise<
|
|
144
|
+
export type RevalidateCache = ({ routeItem, pathname, }: RevalidateCacheArgs) => Promise<{
|
|
145
|
+
data: unknown;
|
|
146
|
+
error: unknown;
|
|
147
|
+
}>;
|
|
142
148
|
export type Options = Partial<{
|
|
143
149
|
onSuccess: (args: unknown) => void;
|
|
144
150
|
onError: (args: unknown) => void;
|
|
145
151
|
}> | undefined;
|
|
152
|
+
export type InvalidateResult = {
|
|
153
|
+
path: string;
|
|
154
|
+
data: unknown;
|
|
155
|
+
};
|
|
146
156
|
export {};
|
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import { type ComponentType, type ReactElement } from 'react';
|
|
2
2
|
export declare const createLazyComponent: (importFn: () => Promise<{
|
|
3
3
|
default: ComponentType<unknown>;
|
|
4
|
-
}>, fallback?: ReactElement | (() => ReactElement)) =>
|
|
4
|
+
}>, fallback?: ReactElement | (() => ReactElement)) => {
|
|
5
|
+
Component: () => import("react/jsx-runtime").JSX.Element;
|
|
6
|
+
preloadElement: () => Promise<{
|
|
7
|
+
default: ComponentType<unknown>;
|
|
8
|
+
}>;
|
|
9
|
+
};
|