pejay-ui 1.2.2 → 1.3.1
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 +17 -2
- package/package.json +2 -2
- package/registry.json +33 -1
- package/templates/notes/create-pejay.md +222 -0
- package/templates/notes/notes-v1.md +516 -0
- package/templates/notes/notes-v2.md +764 -0
- package/templates/notes/notes-v3.md +574 -0
- package/templates/notes/notes-v4.md +811 -0
- package/templates/notes/notes-v5.md +579 -0
- package/templates/notes/notes-vf+1.md +311 -0
- package/templates/notes/notes-vfinal.md +852 -0
- package/templates/scaffolds/axios/api/index.ts +40 -0
- package/templates/scaffolds/axios/api/one.api.ts +94 -0
- package/templates/scaffolds/axios/endpoints.ts +9 -0
- package/templates/scaffolds/axios/index.ts +26 -0
- package/templates/scaffolds/axios/interceptors.ts +103 -0
- package/templates/scaffolds/axios/request.ts +32 -0
- package/templates/scaffolds/react-router/hook/useRouterSearch.ts +8 -0
- package/templates/scaffolds/react-router/router/guards/private.route.tsx +1 -0
- package/templates/scaffolds/react-router/router/index.ts +26 -0
- package/templates/scaffolds/react-router/router/layouts/error.layout.tsx +1 -1
- package/templates/scaffolds/redux-store/middlewares.ts +0 -0
- package/templates/scaffolds/redux-store/reducers.ts +30 -0
- package/templates/scaffolds/redux-store/selector/one.selector.ts +43 -0
- package/templates/scaffolds/redux-store/selector/two.selector.ts +11 -0
- package/templates/scaffolds/redux-store/slices/one.slice.ts +202 -0
- package/templates/scaffolds/redux-store/slices/two.slice.ts +21 -0
- package/templates/scaffolds/redux-store/store.ts +38 -0
- package/templates/scaffolds/rtk-query/baseApi.ts +24 -0
- package/templates/scaffolds/rtk-query/baseQuery.ts +12 -0
- package/templates/scaffolds/rtk-query/endpoints/api.one.ts +82 -0
- package/templates/scaffolds/rtk-query/endpoints/index.ts +1 -0
- package/templates/scaffolds/rtk-query/middlewares.ts +11 -0
- package/templates/scaffolds/rtk-query/queryTags.ts +13 -0
- package/templates/scaffolds/tanstack-query/api-base.ts +68 -68
- package/templates/scaffolds/tanstack-query/api-queries.ts +0 -19
- package/templates/scaffolds/tanstack-query/client.ts +8 -0
- package/templates/scaffolds/tanstack-query/module/index.ts +12 -12
- package/templates/scaffolds/tanstack-query/module/keys.ts +17 -17
- package/templates/scaffolds/tanstack-query/module/mappers.ts +15 -15
- package/templates/scaffolds/tanstack-query/module/mutations.ts +59 -55
- package/templates/scaffolds/tanstack-query/module/queries.ts +145 -156
- package/templates/scaffolds/tanstack-query/module/services.ts +74 -66
- package/templates/scaffolds/tanstack-router/layout/404.layout.tsx +3 -0
- package/templates/scaffolds/tanstack-router/layout/app.layout.tsx +10 -0
- package/templates/scaffolds/tanstack-router/layout/auth.layout.tsx +10 -0
- package/templates/scaffolds/tanstack-router/layout/error.layout.tsx +3 -0
- package/templates/scaffolds/tanstack-router/page/auth/login.tsx +3 -0
- package/templates/scaffolds/tanstack-router/page/one/index.tsx +3 -0
- package/templates/scaffolds/tanstack-router/page/one/one-id.tsx +128 -0
- package/templates/scaffolds/tanstack-router/router.ts +90 -0
- package/templates/scaffolds/tanstack-router/routes/_404.tsx +0 -0
- package/templates/scaffolds/tanstack-router/routes/__root.tsx +9 -0
- package/templates/scaffolds/tanstack-router/routes/_app.tsx +6 -0
- package/templates/scaffolds/tanstack-router/routes/_auth.tsx +6 -0
- package/templates/scaffolds/tanstack-router/routes/_error.tsx +0 -0
- package/templates/scaffolds/tanstack-router/routes/auth/login.tsx +6 -0
- package/templates/scaffolds/tanstack-router/routes/one/$id.tsx +191 -0
- package/templates/scaffolds/tanstack-router/routes/one/index.tsx +6 -0
- package/templates/scripts/setup.bat +284 -0
- package/templates/scripts/setup.ps1 +318 -0
|
@@ -0,0 +1,764 @@
|
|
|
1
|
+
# React Router vs TanStack Router
|
|
2
|
+
|
|
3
|
+
## Philosophy
|
|
4
|
+
|
|
5
|
+
### React Router
|
|
6
|
+
|
|
7
|
+
Focuses on:
|
|
8
|
+
|
|
9
|
+
```txt
|
|
10
|
+
Routing
|
|
11
|
+
Navigation
|
|
12
|
+
Loaders
|
|
13
|
+
Actions
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Type safety is limited and often requires manual typing.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
### TanStack Router
|
|
21
|
+
|
|
22
|
+
Focuses on:
|
|
23
|
+
|
|
24
|
+
```txt
|
|
25
|
+
Routing
|
|
26
|
+
Type Safety
|
|
27
|
+
Search Params
|
|
28
|
+
Loaders
|
|
29
|
+
TanStack Query Integration
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Everything revolves around strongly typed routes.
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
# Route Definition
|
|
37
|
+
|
|
38
|
+
## React Router
|
|
39
|
+
|
|
40
|
+
```tsx
|
|
41
|
+
{
|
|
42
|
+
path: "/users/:id",
|
|
43
|
+
Component: UserDetails,
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
or
|
|
48
|
+
|
|
49
|
+
```tsx
|
|
50
|
+
<Route
|
|
51
|
+
path="/users/:id"
|
|
52
|
+
element={<UserDetails />}
|
|
53
|
+
/>
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## TanStack Router
|
|
59
|
+
|
|
60
|
+
```tsx
|
|
61
|
+
export const Route = createFileRoute(
|
|
62
|
+
"/users/$id"
|
|
63
|
+
)({
|
|
64
|
+
component: UserDetails,
|
|
65
|
+
});
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
# Route Params
|
|
71
|
+
|
|
72
|
+
URL:
|
|
73
|
+
|
|
74
|
+
```txt
|
|
75
|
+
/users/123
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## React Router
|
|
81
|
+
|
|
82
|
+
```tsx
|
|
83
|
+
import { useParams } from "react-router-dom";
|
|
84
|
+
|
|
85
|
+
const { id } = useParams();
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Return type:
|
|
89
|
+
|
|
90
|
+
```tsx
|
|
91
|
+
{
|
|
92
|
+
id?: string;
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Usually requires manual validation.
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## TanStack Router
|
|
101
|
+
|
|
102
|
+
```tsx
|
|
103
|
+
const { id } = Route.useParams();
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Return type:
|
|
107
|
+
|
|
108
|
+
```tsx
|
|
109
|
+
{
|
|
110
|
+
id: string;
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Fully typed from route definition.
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
# Search Params
|
|
119
|
+
|
|
120
|
+
URL:
|
|
121
|
+
|
|
122
|
+
```txt
|
|
123
|
+
/users?search=john&type=active
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## React Router
|
|
129
|
+
|
|
130
|
+
Read:
|
|
131
|
+
|
|
132
|
+
```tsx
|
|
133
|
+
const [searchParams] =
|
|
134
|
+
useSearchParams();
|
|
135
|
+
|
|
136
|
+
const search =
|
|
137
|
+
searchParams.get("search");
|
|
138
|
+
|
|
139
|
+
const type =
|
|
140
|
+
searchParams.get("type");
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Return:
|
|
144
|
+
|
|
145
|
+
```tsx
|
|
146
|
+
string | null
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
every time.
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
Write:
|
|
154
|
+
|
|
155
|
+
```tsx
|
|
156
|
+
setSearchParams({
|
|
157
|
+
search: "john",
|
|
158
|
+
type: "active",
|
|
159
|
+
});
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## TanStack Router
|
|
165
|
+
|
|
166
|
+
Route:
|
|
167
|
+
|
|
168
|
+
```tsx
|
|
169
|
+
validateSearch: (search) => ({
|
|
170
|
+
search:
|
|
171
|
+
typeof search.search === "string"
|
|
172
|
+
? search.search
|
|
173
|
+
: "",
|
|
174
|
+
|
|
175
|
+
type:
|
|
176
|
+
typeof search.type === "string"
|
|
177
|
+
? search.type
|
|
178
|
+
: "",
|
|
179
|
+
})
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Read:
|
|
183
|
+
|
|
184
|
+
```tsx
|
|
185
|
+
const search = Route.useSearch();
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
Result:
|
|
189
|
+
|
|
190
|
+
```tsx
|
|
191
|
+
{
|
|
192
|
+
search: string;
|
|
193
|
+
type: string;
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Write:
|
|
198
|
+
|
|
199
|
+
```tsx
|
|
200
|
+
navigate({
|
|
201
|
+
search: {
|
|
202
|
+
search: "john",
|
|
203
|
+
type: "active",
|
|
204
|
+
},
|
|
205
|
+
});
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
# Navigation
|
|
211
|
+
|
|
212
|
+
## React Router
|
|
213
|
+
|
|
214
|
+
### Link
|
|
215
|
+
|
|
216
|
+
```tsx
|
|
217
|
+
<Link to="/users">
|
|
218
|
+
Users
|
|
219
|
+
</Link>
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
---
|
|
223
|
+
|
|
224
|
+
### useNavigate
|
|
225
|
+
|
|
226
|
+
```tsx
|
|
227
|
+
const navigate =
|
|
228
|
+
useNavigate();
|
|
229
|
+
|
|
230
|
+
navigate("/users");
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
---
|
|
234
|
+
|
|
235
|
+
### Navigate Component
|
|
236
|
+
|
|
237
|
+
```tsx
|
|
238
|
+
<Navigate
|
|
239
|
+
to="/login"
|
|
240
|
+
replace
|
|
241
|
+
/>
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
Often used for redirects.
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
## TanStack Router
|
|
249
|
+
|
|
250
|
+
### Link
|
|
251
|
+
|
|
252
|
+
```tsx
|
|
253
|
+
<Link to="/users">
|
|
254
|
+
Users
|
|
255
|
+
</Link>
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
---
|
|
259
|
+
|
|
260
|
+
### useNavigate
|
|
261
|
+
|
|
262
|
+
```tsx
|
|
263
|
+
const navigate =
|
|
264
|
+
useNavigate();
|
|
265
|
+
|
|
266
|
+
navigate({
|
|
267
|
+
to: "/users",
|
|
268
|
+
});
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
---
|
|
272
|
+
|
|
273
|
+
### router.navigate
|
|
274
|
+
|
|
275
|
+
```tsx
|
|
276
|
+
router.navigate({
|
|
277
|
+
to: "/users",
|
|
278
|
+
});
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
Useful outside React components.
|
|
282
|
+
|
|
283
|
+
---
|
|
284
|
+
|
|
285
|
+
### redirect
|
|
286
|
+
|
|
287
|
+
```tsx
|
|
288
|
+
throw redirect({
|
|
289
|
+
to: "/login",
|
|
290
|
+
});
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
Common in guards and loaders.
|
|
294
|
+
|
|
295
|
+
---
|
|
296
|
+
|
|
297
|
+
# Loader Data
|
|
298
|
+
|
|
299
|
+
## React Router
|
|
300
|
+
|
|
301
|
+
Loader:
|
|
302
|
+
|
|
303
|
+
```tsx
|
|
304
|
+
loader: async () => {
|
|
305
|
+
return {
|
|
306
|
+
name: "John",
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
Read:
|
|
312
|
+
|
|
313
|
+
```tsx
|
|
314
|
+
const data =
|
|
315
|
+
useLoaderData();
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
---
|
|
319
|
+
|
|
320
|
+
## TanStack Router
|
|
321
|
+
|
|
322
|
+
Loader:
|
|
323
|
+
|
|
324
|
+
```tsx
|
|
325
|
+
loader: async () => {
|
|
326
|
+
return {
|
|
327
|
+
name: "John",
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
Read:
|
|
333
|
+
|
|
334
|
+
```tsx
|
|
335
|
+
const data =
|
|
336
|
+
Route.useLoaderData();
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
---
|
|
340
|
+
|
|
341
|
+
# Route Context
|
|
342
|
+
|
|
343
|
+
## React Router
|
|
344
|
+
|
|
345
|
+
No route-specific hook.
|
|
346
|
+
|
|
347
|
+
Usually:
|
|
348
|
+
|
|
349
|
+
```tsx
|
|
350
|
+
Context API
|
|
351
|
+
Redux
|
|
352
|
+
Zustand
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
---
|
|
356
|
+
|
|
357
|
+
## TanStack Router
|
|
358
|
+
|
|
359
|
+
```tsx
|
|
360
|
+
const context =
|
|
361
|
+
Route.useRouteContext();
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
Accesses route context directly.
|
|
365
|
+
|
|
366
|
+
---
|
|
367
|
+
|
|
368
|
+
# Route Matching
|
|
369
|
+
|
|
370
|
+
## React Router
|
|
371
|
+
|
|
372
|
+
```tsx
|
|
373
|
+
const match =
|
|
374
|
+
useMatch("/users/:id");
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
---
|
|
378
|
+
|
|
379
|
+
## TanStack Router
|
|
380
|
+
|
|
381
|
+
```tsx
|
|
382
|
+
const match =
|
|
383
|
+
Route.useMatch();
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
Route-aware and typed.
|
|
387
|
+
|
|
388
|
+
---
|
|
389
|
+
|
|
390
|
+
# Common Route Hooks
|
|
391
|
+
|
|
392
|
+
## React Router
|
|
393
|
+
|
|
394
|
+
```tsx
|
|
395
|
+
useParams()
|
|
396
|
+
useSearchParams()
|
|
397
|
+
useNavigate()
|
|
398
|
+
useLocation()
|
|
399
|
+
useLoaderData()
|
|
400
|
+
useMatches()
|
|
401
|
+
useMatch()
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
---
|
|
405
|
+
|
|
406
|
+
## TanStack Router
|
|
407
|
+
|
|
408
|
+
```tsx
|
|
409
|
+
Route.useParams()
|
|
410
|
+
Route.useSearch()
|
|
411
|
+
Route.useLoaderData()
|
|
412
|
+
Route.useRouteContext()
|
|
413
|
+
Route.useMatch()
|
|
414
|
+
|
|
415
|
+
useNavigate()
|
|
416
|
+
useRouter()
|
|
417
|
+
useRouterState()
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
---
|
|
421
|
+
|
|
422
|
+
# Query Integration
|
|
423
|
+
|
|
424
|
+
## React Router
|
|
425
|
+
|
|
426
|
+
Typical pattern:
|
|
427
|
+
|
|
428
|
+
```tsx
|
|
429
|
+
const { id } =
|
|
430
|
+
useParams();
|
|
431
|
+
|
|
432
|
+
const { data } =
|
|
433
|
+
useSuspenseQuery(
|
|
434
|
+
apiQueries.users.detail(id)
|
|
435
|
+
);
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
No special integration.
|
|
439
|
+
|
|
440
|
+
---
|
|
441
|
+
|
|
442
|
+
## TanStack Router
|
|
443
|
+
|
|
444
|
+
Loader:
|
|
445
|
+
|
|
446
|
+
```tsx
|
|
447
|
+
loader:
|
|
448
|
+
({ context, params }) =>
|
|
449
|
+
context.queryClient
|
|
450
|
+
.ensureQueryData(
|
|
451
|
+
apiQueries.users.detail(
|
|
452
|
+
params.id
|
|
453
|
+
)
|
|
454
|
+
)
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
Component:
|
|
458
|
+
|
|
459
|
+
```tsx
|
|
460
|
+
const { id } =
|
|
461
|
+
Route.useParams();
|
|
462
|
+
|
|
463
|
+
const { data } =
|
|
464
|
+
useSuspenseQuery(
|
|
465
|
+
apiQueries.users.detail(id)
|
|
466
|
+
);
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
Perfect prefetch integration.
|
|
470
|
+
|
|
471
|
+
---
|
|
472
|
+
|
|
473
|
+
# Guards
|
|
474
|
+
|
|
475
|
+
## React Router
|
|
476
|
+
|
|
477
|
+
Common pattern:
|
|
478
|
+
|
|
479
|
+
```tsx
|
|
480
|
+
function PrivateRoute() {
|
|
481
|
+
if (!isAuthenticated()) {
|
|
482
|
+
return (
|
|
483
|
+
<Navigate
|
|
484
|
+
to="/login"
|
|
485
|
+
/>
|
|
486
|
+
);
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
return <Outlet />;
|
|
490
|
+
}
|
|
491
|
+
```
|
|
492
|
+
|
|
493
|
+
---
|
|
494
|
+
|
|
495
|
+
## TanStack Router
|
|
496
|
+
|
|
497
|
+
Common pattern:
|
|
498
|
+
|
|
499
|
+
```tsx
|
|
500
|
+
export function PrivateRoute({
|
|
501
|
+
context,
|
|
502
|
+
}) {
|
|
503
|
+
if (
|
|
504
|
+
!context.auth
|
|
505
|
+
.isAuthenticated
|
|
506
|
+
) {
|
|
507
|
+
throw redirect({
|
|
508
|
+
to: "/login",
|
|
509
|
+
});
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
---
|
|
515
|
+
|
|
516
|
+
# Code Splitting
|
|
517
|
+
|
|
518
|
+
## React Router
|
|
519
|
+
|
|
520
|
+
Route level:
|
|
521
|
+
|
|
522
|
+
```tsx
|
|
523
|
+
lazy: async () => {
|
|
524
|
+
const module =
|
|
525
|
+
await import(
|
|
526
|
+
"./users"
|
|
527
|
+
);
|
|
528
|
+
|
|
529
|
+
return {
|
|
530
|
+
Component:
|
|
531
|
+
module.default,
|
|
532
|
+
};
|
|
533
|
+
}
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
Manual.
|
|
537
|
+
|
|
538
|
+
---
|
|
539
|
+
|
|
540
|
+
## TanStack Router
|
|
541
|
+
|
|
542
|
+
Route level:
|
|
543
|
+
|
|
544
|
+
```txt
|
|
545
|
+
Auto Route Splitting
|
|
546
|
+
```
|
|
547
|
+
|
|
548
|
+
via plugin/build tooling.
|
|
549
|
+
|
|
550
|
+
No manual imports needed.
|
|
551
|
+
|
|
552
|
+
---
|
|
553
|
+
|
|
554
|
+
# Component Splitting
|
|
555
|
+
|
|
556
|
+
Both use React.lazy.
|
|
557
|
+
|
|
558
|
+
```tsx
|
|
559
|
+
const HistoryDrawer =
|
|
560
|
+
lazy(() =>
|
|
561
|
+
import(
|
|
562
|
+
"./HistoryDrawer"
|
|
563
|
+
)
|
|
564
|
+
);
|
|
565
|
+
```
|
|
566
|
+
|
|
567
|
+
with:
|
|
568
|
+
|
|
569
|
+
```tsx
|
|
570
|
+
<Suspense
|
|
571
|
+
fallback={
|
|
572
|
+
<Loading />
|
|
573
|
+
}
|
|
574
|
+
>
|
|
575
|
+
<HistoryDrawer />
|
|
576
|
+
</Suspense>
|
|
577
|
+
```
|
|
578
|
+
|
|
579
|
+
No difference.
|
|
580
|
+
|
|
581
|
+
---
|
|
582
|
+
|
|
583
|
+
# Type Safety
|
|
584
|
+
|
|
585
|
+
## React Router
|
|
586
|
+
|
|
587
|
+
```tsx
|
|
588
|
+
navigate(
|
|
589
|
+
`/users/${id}`
|
|
590
|
+
);
|
|
591
|
+
```
|
|
592
|
+
|
|
593
|
+
No route validation.
|
|
594
|
+
|
|
595
|
+
---
|
|
596
|
+
|
|
597
|
+
## TanStack Router
|
|
598
|
+
|
|
599
|
+
```tsx
|
|
600
|
+
navigate({
|
|
601
|
+
to: "/users/$id",
|
|
602
|
+
|
|
603
|
+
params: {
|
|
604
|
+
id: "123",
|
|
605
|
+
},
|
|
606
|
+
});
|
|
607
|
+
```
|
|
608
|
+
|
|
609
|
+
Compile-time validation.
|
|
610
|
+
|
|
611
|
+
---
|
|
612
|
+
|
|
613
|
+
# Search Param Type Safety
|
|
614
|
+
|
|
615
|
+
## React Router
|
|
616
|
+
|
|
617
|
+
```tsx
|
|
618
|
+
searchParams.get(
|
|
619
|
+
"page"
|
|
620
|
+
);
|
|
621
|
+
```
|
|
622
|
+
|
|
623
|
+
Returns:
|
|
624
|
+
|
|
625
|
+
```tsx
|
|
626
|
+
string | null
|
|
627
|
+
```
|
|
628
|
+
|
|
629
|
+
Must manually parse.
|
|
630
|
+
|
|
631
|
+
---
|
|
632
|
+
|
|
633
|
+
## TanStack Router
|
|
634
|
+
|
|
635
|
+
```tsx
|
|
636
|
+
const search =
|
|
637
|
+
Route.useSearch();
|
|
638
|
+
```
|
|
639
|
+
|
|
640
|
+
Already validated.
|
|
641
|
+
|
|
642
|
+
```tsx
|
|
643
|
+
search.page
|
|
644
|
+
search.type
|
|
645
|
+
```
|
|
646
|
+
|
|
647
|
+
Strongly typed.
|
|
648
|
+
|
|
649
|
+
---
|
|
650
|
+
|
|
651
|
+
# Most Common APIs
|
|
652
|
+
|
|
653
|
+
## React Router Daily Usage
|
|
654
|
+
|
|
655
|
+
```tsx
|
|
656
|
+
useParams()
|
|
657
|
+
useSearchParams()
|
|
658
|
+
useNavigate()
|
|
659
|
+
useLoaderData()
|
|
660
|
+
|
|
661
|
+
<Link />
|
|
662
|
+
<Outlet />
|
|
663
|
+
<Navigate />
|
|
664
|
+
```
|
|
665
|
+
|
|
666
|
+
---
|
|
667
|
+
|
|
668
|
+
## TanStack Router Daily Usage
|
|
669
|
+
|
|
670
|
+
```tsx
|
|
671
|
+
Route.useParams()
|
|
672
|
+
Route.useSearch()
|
|
673
|
+
|
|
674
|
+
useNavigate()
|
|
675
|
+
|
|
676
|
+
Route.useLoaderData()
|
|
677
|
+
|
|
678
|
+
useSuspenseQuery()
|
|
679
|
+
|
|
680
|
+
<Link />
|
|
681
|
+
<Outlet />
|
|
682
|
+
|
|
683
|
+
redirect()
|
|
684
|
+
```
|
|
685
|
+
|
|
686
|
+
---
|
|
687
|
+
|
|
688
|
+
# Recommended Mental Model
|
|
689
|
+
|
|
690
|
+
## React Router
|
|
691
|
+
|
|
692
|
+
```txt
|
|
693
|
+
URL
|
|
694
|
+
↓
|
|
695
|
+
useParams
|
|
696
|
+
|
|
697
|
+
URL Search Params
|
|
698
|
+
↓
|
|
699
|
+
useSearchParams
|
|
700
|
+
|
|
701
|
+
Loader
|
|
702
|
+
↓
|
|
703
|
+
useLoaderData
|
|
704
|
+
```
|
|
705
|
+
|
|
706
|
+
---
|
|
707
|
+
|
|
708
|
+
## TanStack Router
|
|
709
|
+
|
|
710
|
+
```txt
|
|
711
|
+
URL Params
|
|
712
|
+
↓
|
|
713
|
+
Route.useParams()
|
|
714
|
+
|
|
715
|
+
Search Params
|
|
716
|
+
↓
|
|
717
|
+
Route.useSearch()
|
|
718
|
+
|
|
719
|
+
Loader Data
|
|
720
|
+
↓
|
|
721
|
+
Route.useLoaderData()
|
|
722
|
+
|
|
723
|
+
Query Cache
|
|
724
|
+
↓
|
|
725
|
+
useSuspenseQuery()
|
|
726
|
+
```
|
|
727
|
+
|
|
728
|
+
---
|
|
729
|
+
|
|
730
|
+
# Which To Choose?
|
|
731
|
+
|
|
732
|
+
## React Router
|
|
733
|
+
|
|
734
|
+
Choose when:
|
|
735
|
+
|
|
736
|
+
* Small to medium apps
|
|
737
|
+
* Simpler requirements
|
|
738
|
+
* Team already familiar with React Router
|
|
739
|
+
* Type safety is not a major concern
|
|
740
|
+
|
|
741
|
+
---
|
|
742
|
+
|
|
743
|
+
## TanStack Router
|
|
744
|
+
|
|
745
|
+
Choose when:
|
|
746
|
+
|
|
747
|
+
* Large applications
|
|
748
|
+
* CRM/Admin Panels
|
|
749
|
+
* Heavy use of TanStack Query
|
|
750
|
+
* Strong TypeScript usage
|
|
751
|
+
* Complex search params
|
|
752
|
+
* Need route-level type safety
|
|
753
|
+
|
|
754
|
+
Examples:
|
|
755
|
+
|
|
756
|
+
```txt
|
|
757
|
+
Prime Hearing
|
|
758
|
+
Fleet Nexa
|
|
759
|
+
ERP
|
|
760
|
+
CRM
|
|
761
|
+
Analytics Dashboards
|
|
762
|
+
```
|
|
763
|
+
|
|
764
|
+
These are ideal candidates for TanStack Router.
|