@tanstack/react-router 0.0.1-beta.165 → 0.0.1-beta.167

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tanstack/react-router",
3
3
  "author": "Tanner Linsley",
4
- "version": "0.0.1-beta.165",
4
+ "version": "0.0.1-beta.167",
5
5
  "license": "MIT",
6
6
  "repository": "tanstack/router",
7
7
  "homepage": "https://tanstack.com/router",
@@ -43,8 +43,8 @@
43
43
  "tiny-invariant": "^1.3.1",
44
44
  "tiny-warning": "^1.0.3",
45
45
  "@gisatcz/cross-package-react-context": "^0.2.0",
46
- "@tanstack/router-core": "0.0.1-beta.165",
47
- "@tanstack/react-store": "0.0.1-beta.165"
46
+ "@tanstack/router-core": "0.0.1-beta.167",
47
+ "@tanstack/react-store": "0.0.1-beta.167"
48
48
  },
49
49
  "scripts": {
50
50
  "build": "rollup --config rollup.config.js"
@@ -0,0 +1,40 @@
1
+ import { DeferredPromise, isDehydratedDeferred } from '@tanstack/router-core'
2
+ import { useRouter } from '.'
3
+
4
+ export type DeferredOptions<T> = {
5
+ promise: DeferredPromise<T>
6
+ }
7
+
8
+ export function useDeferred<T>({ promise }: DeferredOptions<T>): [T] {
9
+ const router = useRouter()
10
+
11
+ let state = promise.__deferredState
12
+ const key = `__TSR__DEFERRED__${state.uid}`
13
+
14
+ if (isDehydratedDeferred(promise)) {
15
+ state = router.hydrateData(key)!
16
+ promise = Promise.resolve(state.data) as DeferredPromise<any>
17
+ promise.__deferredState = state
18
+ }
19
+
20
+ if (state.status === 'pending') {
21
+ throw promise
22
+ }
23
+
24
+ if (state.status === 'error') {
25
+ throw state.error
26
+ }
27
+
28
+ router.dehydrateData(key, state)
29
+
30
+ return [state.data]
31
+ }
32
+
33
+ export function Deferred<T>(
34
+ props: DeferredOptions<T> & {
35
+ children: (result: T) => JSX.Element
36
+ },
37
+ ) {
38
+ const awaited = useDeferred(props)
39
+ return props.children(...awaited)
40
+ }
package/src/index.tsx CHANGED
@@ -35,21 +35,24 @@ import {
35
35
  RouteById,
36
36
  ParseRoute,
37
37
  AllParams,
38
+ rootRouteId,
39
+ AnyPathParams,
38
40
  } from '@tanstack/router-core'
39
41
 
40
42
  //
41
43
 
42
44
  export * from '@tanstack/router-core'
43
45
  export * from './scroll-restoration'
46
+ export * from './deferred'
44
47
 
45
48
  export { useStore }
46
49
 
47
50
  declare module '@tanstack/router-core' {
48
- interface RegisterRouteComponent<TProps extends Record<string, any>> {
51
+ interface RegisterRouteComponent<TProps> {
49
52
  RouteComponent: RouteComponent<TProps>
50
53
  }
51
54
 
52
- interface RegisterRouteErrorComponent<TProps extends Record<string, any>> {
55
+ interface RegisterRouteErrorComponent<TProps> {
53
56
  RouteErrorComponent: RouteComponent<TProps>
54
57
  }
55
58
 
@@ -128,6 +131,102 @@ declare module '@tanstack/router-core' {
128
131
  select?: (search: TAllParams) => TSelected
129
132
  }) => TStrict extends true ? TSelected : TSelected | undefined
130
133
  }
134
+
135
+ interface RegisterRouteProps<
136
+ TLoader = unknown,
137
+ TFullSearchSchema extends AnySearchSchema = AnySearchSchema,
138
+ TAllParams extends AnyPathParams = AnyPathParams,
139
+ TRouteContext extends AnyContext = AnyContext,
140
+ TAllContext extends AnyContext = AnyContext,
141
+ > {
142
+ RouteProps: RouteProps<
143
+ TLoader,
144
+ TFullSearchSchema,
145
+ TAllParams,
146
+ TRouteContext,
147
+ TAllContext
148
+ >
149
+ }
150
+
151
+ interface RegisterPendingRouteProps<
152
+ TFullSearchSchema extends AnySearchSchema = AnySearchSchema,
153
+ TAllParams extends AnyPathParams = AnyPathParams,
154
+ TRouteContext extends AnyContext = AnyContext,
155
+ TAllContext extends AnyContext = AnyContext,
156
+ > {
157
+ PendingRouteProps: Omit<
158
+ RouteProps<
159
+ unknown,
160
+ TFullSearchSchema,
161
+ TAllParams,
162
+ TRouteContext,
163
+ TAllContext
164
+ >,
165
+ 'useLoader'
166
+ >
167
+ }
168
+
169
+ interface RegisterErrorRouteProps<
170
+ TFullSearchSchema extends AnySearchSchema = AnySearchSchema,
171
+ TAllParams extends AnyPathParams = AnyPathParams,
172
+ TRouteContext extends AnyContext = AnyContext,
173
+ TAllContext extends AnyContext = AnyContext,
174
+ > {
175
+ ErrorRouteProps: {
176
+ error: unknown
177
+ info: { componentStack: string }
178
+ } & Omit<
179
+ RouteProps<
180
+ unknown,
181
+ TFullSearchSchema,
182
+ TAllParams,
183
+ TRouteContext,
184
+ TAllContext
185
+ >,
186
+ 'useLoader'
187
+ >
188
+ }
189
+ }
190
+
191
+ export type RouteProps<
192
+ TLoader = unknown,
193
+ TFullSearchSchema extends AnySearchSchema = AnySearchSchema,
194
+ TAllParams extends AnyPathParams = AnyPathParams,
195
+ TRouteContext extends AnyContext = AnyContext,
196
+ TAllContext extends AnyContext = AnyContext,
197
+ > = {
198
+ useLoader: <TStrict extends boolean = true, TSelected = TLoader>(opts?: {
199
+ strict?: TStrict
200
+ select?: (search: TLoader) => TSelected
201
+ }) => TStrict extends true
202
+ ? UseLoaderResult<TSelected>
203
+ : UseLoaderResult<TSelected> | undefined
204
+ useMatch: <TStrict extends boolean = true, TSelected = TAllContext>(opts?: {
205
+ strict?: TStrict
206
+ select?: (search: TAllContext) => TSelected
207
+ }) => TStrict extends true ? TSelected : TSelected | undefined
208
+ useContext: <TStrict extends boolean = true, TSelected = TAllContext>(opts?: {
209
+ strict?: TStrict
210
+ select?: (search: TAllContext) => TSelected
211
+ }) => TStrict extends true ? TSelected : TSelected | undefined
212
+ useRouteContext: <
213
+ TStrict extends boolean = true,
214
+ TSelected = TRouteContext,
215
+ >(opts?: {
216
+ strict?: TStrict
217
+ select?: (search: TRouteContext) => TSelected
218
+ }) => TStrict extends true ? TSelected : TSelected | undefined
219
+ useSearch: <
220
+ TStrict extends boolean = true,
221
+ TSelected = TFullSearchSchema,
222
+ >(opts?: {
223
+ strict?: TStrict
224
+ select?: (search: TFullSearchSchema) => TSelected
225
+ }) => TStrict extends true ? TSelected : TSelected | undefined
226
+ useParams: <TStrict extends boolean = true, TSelected = TAllParams>(opts?: {
227
+ strict?: TStrict
228
+ select?: (search: TAllParams) => TSelected
229
+ }) => TStrict extends true ? TSelected : TSelected | undefined
131
230
  }
132
231
 
133
232
  Route.__onInit = (route) => {
@@ -471,13 +570,11 @@ export function RouterProvider<
471
570
  const Wrap = router.options.Wrap || React.Fragment
472
571
 
473
572
  return (
474
- <React.Suspense fallback={null}>
475
- <Wrap>
476
- <routerContext.Provider value={router as any}>
477
- <Matches />
478
- </routerContext.Provider>
479
- </Wrap>
480
- </React.Suspense>
573
+ <Wrap>
574
+ <routerContext.Provider value={router as any}>
575
+ <Matches />
576
+ </routerContext.Provider>
577
+ </Wrap>
481
578
  )
482
579
  }
483
580
 
@@ -503,6 +600,7 @@ function Matches() {
503
600
  <matchIdsContext.Provider value={[undefined!, ...matchIds]}>
504
601
  <CatchBoundary
505
602
  errorComponent={ErrorComponent}
603
+ route={router.getRoute(rootRouteId)}
506
604
  onCatch={() => {
507
605
  warning(
508
606
  false,
@@ -795,7 +893,6 @@ function Match({ matchIds }: { matchIds: string[] }) {
795
893
  <matchIdsContext.Provider value={matchIds}>
796
894
  <ResolvedSuspenseBoundary
797
895
  fallback={React.createElement(PendingComponent, {
798
- useLoader: route.useLoader,
799
896
  useMatch: route.useMatch,
800
897
  useContext: route.useContext,
801
898
  useRouteContext: route.useRouteContext,
@@ -806,6 +903,7 @@ function Match({ matchIds }: { matchIds: string[] }) {
806
903
  <ResolvedCatchBoundary
807
904
  key={route.id}
808
905
  errorComponent={errorComponent}
906
+ route={route}
809
907
  onCatch={() => {
810
908
  warning(false, `Error in route match: ${matchId}`)
811
909
  }}
@@ -915,6 +1013,7 @@ export function useHydrate() {
915
1013
  class CatchBoundary extends React.Component<{
916
1014
  children: any
917
1015
  errorComponent: any
1016
+ route: AnyRoute
918
1017
  onCatch: (error: any, info: any) => void
919
1018
  }> {
920
1019
  state = {
@@ -942,6 +1041,7 @@ class CatchBoundary extends React.Component<{
942
1041
  function CatchBoundaryInner(props: {
943
1042
  children: any
944
1043
  errorComponent: any
1044
+ route: AnyRoute
945
1045
  errorState: { error: unknown; info: any }
946
1046
  reset: () => void
947
1047
  }) {
@@ -973,7 +1073,14 @@ function CatchBoundaryInner(props: {
973
1073
  }, [props.errorState.error])
974
1074
 
975
1075
  if (props.errorState.error && activeErrorState.error) {
976
- return React.createElement(errorComponent, activeErrorState)
1076
+ return React.createElement(errorComponent, {
1077
+ ...activeErrorState,
1078
+ useMatch: props.route.useMatch,
1079
+ useContext: props.route.useContext,
1080
+ useRouteContext: props.route.useRouteContext,
1081
+ useSearch: props.route.useSearch,
1082
+ useParams: props.route.useParams,
1083
+ })
977
1084
  }
978
1085
 
979
1086
  return props.children