@tanstack/react-router 1.87.1 → 1.87.2

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,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/react-router",
3
- "version": "1.87.1",
3
+ "version": "1.87.2",
4
4
  "description": "Modern and scalable routing for React applications",
5
5
  "author": "Tanner Linsley",
6
6
  "license": "MIT",
package/src/awaited.tsx CHANGED
@@ -2,7 +2,7 @@ import * as React from 'react'
2
2
  import warning from 'tiny-warning'
3
3
  import { useRouter } from './useRouter'
4
4
  import { defaultSerializeError } from './router'
5
- import { defer } from './defer'
5
+ import { TSR_DEFERRED_PROMISE, defer } from './defer'
6
6
  import { defaultDeserializeError, isServerSideError } from './isServerSideError'
7
7
  import type { DeferredPromise } from './defer'
8
8
 
@@ -14,38 +14,36 @@ export function useAwaited<T>({
14
14
  promise: _promise,
15
15
  }: AwaitOptions<T>): [T, DeferredPromise<T>] {
16
16
  const router = useRouter()
17
- const promise = _promise as DeferredPromise<T>
17
+ const promise = defer(_promise)
18
18
 
19
- defer(promise)
20
-
21
- if (promise.status === 'pending') {
19
+ if (promise[TSR_DEFERRED_PROMISE].status === 'pending') {
22
20
  throw promise
23
21
  }
24
22
 
25
- if (promise.status === 'error') {
23
+ if (promise[TSR_DEFERRED_PROMISE].status === 'error') {
26
24
  if (typeof document !== 'undefined') {
27
- if (isServerSideError(promise.error)) {
25
+ if (isServerSideError(promise[TSR_DEFERRED_PROMISE].error)) {
28
26
  throw (
29
27
  router.options.errorSerializer?.deserialize ?? defaultDeserializeError
30
- )(promise.error.data as any)
28
+ )(promise[TSR_DEFERRED_PROMISE].error.data as any)
31
29
  } else {
32
30
  warning(
33
31
  false,
34
32
  "Encountered a server-side error that doesn't fit the expected shape",
35
33
  )
36
- throw promise.error
34
+ throw promise[TSR_DEFERRED_PROMISE].error
37
35
  }
38
36
  } else {
39
37
  throw {
40
38
  data: (
41
39
  router.options.errorSerializer?.serialize ?? defaultSerializeError
42
- )(promise.error),
40
+ )(promise[TSR_DEFERRED_PROMISE].error),
43
41
  __isServerError: true,
44
42
  }
45
43
  }
46
44
  }
47
-
48
- return [promise.data as any, promise]
45
+ console.log('useAwaited', promise[TSR_DEFERRED_PROMISE])
46
+ return [promise[TSR_DEFERRED_PROMISE].data, promise]
49
47
  }
50
48
 
51
49
  export function Await<T>(
@@ -68,5 +66,7 @@ function AwaitInner<T>(
68
66
  },
69
67
  ): React.JSX.Element {
70
68
  const [data] = useAwaited(props)
69
+ console.log('AwaitInner', data)
70
+
71
71
  return props.children(data) as React.JSX.Element
72
72
  }
package/src/defer.ts CHANGED
@@ -1,25 +1,24 @@
1
1
  import { defaultSerializeError } from './router'
2
2
 
3
+ export const TSR_DEFERRED_PROMISE = Symbol.for('TSR_DEFERRED_PROMISE')
4
+
3
5
  export type DeferredPromiseState<T> = {
4
- uid: string
5
- resolve?: () => void
6
- reject?: () => void
7
- } & (
8
- | {
9
- status: 'pending'
10
- data?: T
11
- error?: unknown
12
- }
13
- | {
14
- status: 'success'
15
- data: T
16
- }
17
- | {
18
- status: 'error'
19
- data?: T
20
- error: unknown
21
- }
22
- )
6
+ [TSR_DEFERRED_PROMISE]:
7
+ | {
8
+ status: 'pending'
9
+ data?: T
10
+ error?: unknown
11
+ }
12
+ | {
13
+ status: 'success'
14
+ data: T
15
+ }
16
+ | {
17
+ status: 'error'
18
+ data?: T
19
+ error: unknown
20
+ }
21
+ }
23
22
 
24
23
  export type DeferredPromise<T> = Promise<T> & DeferredPromiseState<T>
25
24
 
@@ -30,25 +29,25 @@ export function defer<T>(
30
29
  },
31
30
  ) {
32
31
  const promise = _promise as DeferredPromise<T>
32
+ // this is already deferred promise
33
+ if ((promise as any)[TSR_DEFERRED_PROMISE]) {
34
+ return promise
35
+ }
36
+ promise[TSR_DEFERRED_PROMISE] = { status: 'pending' }
33
37
 
34
- if (!(promise as any).status) {
35
- Object.assign(promise, {
36
- status: 'pending',
38
+ promise
39
+ .then((data) => {
40
+ promise[TSR_DEFERRED_PROMISE].status = 'success'
41
+ promise[TSR_DEFERRED_PROMISE].data = data
42
+ console.log('defer then', promise[TSR_DEFERRED_PROMISE])
43
+ })
44
+ .catch((error) => {
45
+ promise[TSR_DEFERRED_PROMISE].status = 'error'
46
+ ;(promise[TSR_DEFERRED_PROMISE] as any).error = {
47
+ data: (options?.serializeError ?? defaultSerializeError)(error),
48
+ __isServerError: true,
49
+ }
37
50
  })
38
-
39
- promise
40
- .then((data) => {
41
- promise.status = 'success' as any
42
- promise.data = data
43
- })
44
- .catch((error) => {
45
- promise.status = 'error' as any
46
- ;(promise as any).error = {
47
- data: (options?.serializeError ?? defaultSerializeError)(error),
48
- __isServerError: true,
49
- }
50
- })
51
- }
52
51
 
53
52
  return promise
54
53
  }
package/src/index.tsx CHANGED
@@ -19,7 +19,7 @@ export type { AwaitOptions } from './awaited'
19
19
 
20
20
  export { ScriptOnce } from './ScriptOnce'
21
21
 
22
- export { defer } from './defer'
22
+ export { defer, TSR_DEFERRED_PROMISE } from './defer'
23
23
  export type { DeferredPromiseState, DeferredPromise } from './defer'
24
24
 
25
25
  export { CatchBoundary, ErrorComponent } from './CatchBoundary'
@@ -262,6 +262,8 @@ export type {
262
262
  RouterListener,
263
263
  AnyRouterWithContext,
264
264
  ExtractedEntry,
265
+ ExtractedStream,
266
+ ExtractedPromise,
265
267
  StreamState,
266
268
  } from './router'
267
269
 
package/src/router.ts CHANGED
@@ -30,6 +30,7 @@ import {
30
30
  import { isRedirect, isResolvedRedirect } from './redirects'
31
31
  import { isNotFound } from './not-found'
32
32
  import { defaultTransformer } from './transformer'
33
+ import type { DeferredPromiseState } from './defer'
33
34
  import type * as React from 'react'
34
35
  import type {
35
36
  HistoryLocation,
@@ -145,16 +146,26 @@ export type InferRouterContext<TRouteTree extends AnyRoute> =
145
146
  ? TRouterContext
146
147
  : AnyContext
147
148
 
148
- export type ExtractedEntry = {
149
+ export interface ExtractedBaseEntry {
149
150
  dataType: '__beforeLoadContext' | 'loaderData'
150
- type: 'promise' | 'stream'
151
+ type: string
151
152
  path: Array<string>
152
- value: any
153
153
  id: number
154
- streamState?: StreamState
155
154
  matchIndex: number
156
155
  }
157
156
 
157
+ export interface ExtractedStream extends ExtractedBaseEntry {
158
+ type: 'stream'
159
+ streamState: StreamState
160
+ }
161
+
162
+ export interface ExtractedPromise extends ExtractedBaseEntry {
163
+ type: 'promise'
164
+ promiseState: DeferredPromiseState<any>
165
+ }
166
+
167
+ export type ExtractedEntry = ExtractedStream | ExtractedPromise
168
+
158
169
  export type StreamState = {
159
170
  promises: Array<ControlledPromise<string | null>>
160
171
  }