@tanstack/react-router 1.31.22 → 1.31.23

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.
@@ -1,10 +1,8 @@
1
+ // eslint-disable-next-line @typescript-eslint/consistent-type-imports
1
2
  import * as React from 'react'
2
- import { flushSync } from 'react-dom'
3
3
  import { Matches } from './Matches'
4
- import { pick, useLayoutEffect } from './utils'
5
- import { useRouter } from './useRouter'
6
- import { useRouterState } from './useRouterState'
7
4
  import { getRouterContext } from './routerContext'
5
+ import { Transitioner } from './Transitioner'
8
6
  import type { NavigateOptions, ToOptions } from './link'
9
7
  import type { ParsedLocation } from './location'
10
8
  import type { AnyRoute } from './route'
@@ -87,17 +85,11 @@ export function RouterContextProvider<
87
85
 
88
86
  const routerContext = getRouterContext()
89
87
 
90
- const pendingElement = router.options.defaultPendingComponent ? (
91
- <router.options.defaultPendingComponent />
92
- ) : null
93
-
94
88
  const provider = (
95
- <React.Suspense fallback={pendingElement}>
96
- <routerContext.Provider value={router}>
97
- {children}
98
- <Transitioner />
99
- </routerContext.Provider>
100
- </React.Suspense>
89
+ <routerContext.Provider value={router}>
90
+ {children}
91
+ <Transitioner />
92
+ </routerContext.Provider>
101
93
  )
102
94
 
103
95
  if (router.options.Wrap) {
@@ -118,129 +110,6 @@ export function RouterProvider<
118
110
  )
119
111
  }
120
112
 
121
- function Transitioner() {
122
- const router = useRouter()
123
- const mountLoadForRouter = React.useRef({ router, mounted: false })
124
- const routerState = useRouterState({
125
- select: (s) =>
126
- pick(s, ['isLoading', 'location', 'resolvedLocation', 'isTransitioning']),
127
- })
128
-
129
- const [isTransitioning, startReactTransition_] = React.useTransition()
130
- // Track pending state changes
131
- const hasPendingMatches = useRouterState({
132
- select: (s) => s.matches.some((d) => d.status === 'pending'),
133
- })
134
-
135
- const previousIsLoading = usePrevious(routerState.isLoading)
136
-
137
- const isAnyPending =
138
- routerState.isLoading || isTransitioning || hasPendingMatches
139
- const previousIsAnyPending = usePrevious(isAnyPending)
140
-
141
- router.startReactTransition = startReactTransition_
142
-
143
- const tryLoad = async () => {
144
- try {
145
- await router.load()
146
- } catch (err) {
147
- console.error(err)
148
- }
149
- }
150
-
151
- // Subscribe to location changes
152
- // and try to load the new location
153
- useLayoutEffect(() => {
154
- const unsub = router.history.subscribe(router.load)
155
-
156
- const nextLocation = router.buildLocation({
157
- to: router.latestLocation.pathname,
158
- search: true,
159
- params: true,
160
- hash: true,
161
- state: true,
162
- })
163
-
164
- if (routerState.location.href !== nextLocation.href) {
165
- router.commitLocation({ ...nextLocation, replace: true })
166
- }
167
-
168
- return () => {
169
- unsub()
170
- }
171
- // eslint-disable-next-line react-hooks/exhaustive-deps
172
- }, [router, router.history])
173
-
174
- // Try to load the initial location
175
- useLayoutEffect(() => {
176
- if (
177
- window.__TSR_DEHYDRATED__ ||
178
- (mountLoadForRouter.current.router === router &&
179
- mountLoadForRouter.current.mounted)
180
- ) {
181
- return
182
- }
183
- mountLoadForRouter.current = { router, mounted: true }
184
- tryLoad()
185
- // eslint-disable-next-line react-hooks/exhaustive-deps
186
- }, [router])
187
-
188
- useLayoutEffect(() => {
189
- // The router was loading and now it's not
190
- if (previousIsLoading && !routerState.isLoading) {
191
- const toLocation = router.state.location
192
- const fromLocation = router.state.resolvedLocation
193
- const pathChanged = fromLocation.href !== toLocation.href
194
-
195
- router.emit({
196
- type: 'onLoad',
197
- fromLocation,
198
- toLocation,
199
- pathChanged,
200
- })
201
-
202
- // if (router.viewTransitionPromise) {
203
- // console.log('resolving view transition promise')
204
- // }
205
-
206
- // router.viewTransitionPromise?.resolve(true)
207
- }
208
- }, [previousIsLoading, router, routerState.isLoading])
209
-
210
- useLayoutEffect(() => {
211
- // The router was pending and now it's not
212
- if (previousIsAnyPending && !isAnyPending) {
213
- const toLocation = router.state.location
214
- const fromLocation = router.state.resolvedLocation
215
- const pathChanged = fromLocation.href !== toLocation.href
216
-
217
- router.emit({
218
- type: 'onResolved',
219
- fromLocation,
220
- toLocation,
221
- pathChanged,
222
- })
223
-
224
- router.__store.setState((s) => ({
225
- ...s,
226
- status: 'idle',
227
- resolvedLocation: s.location,
228
- }))
229
-
230
- if ((document as any).querySelector) {
231
- if (router.state.location.hash !== '') {
232
- const el = document.getElementById(router.state.location.hash)
233
- if (el) {
234
- el.scrollIntoView()
235
- }
236
- }
237
- }
238
- }
239
- }, [isAnyPending, previousIsAnyPending, router])
240
-
241
- return null
242
- }
243
-
244
113
  export function getRouteMatch<TRouteTree extends AnyRoute>(
245
114
  state: RouterState<TRouteTree>,
246
115
  id: string,
@@ -275,15 +144,3 @@ export type RouterProps<
275
144
  >['context']
276
145
  >
277
146
  }
278
-
279
- function usePrevious<T>(value: T): T {
280
- const ref = React.useRef<T>(value)
281
-
282
- if (ref.current !== value) {
283
- const prevValue = ref.current
284
- ref.current = value
285
- return prevValue
286
- } else {
287
- return ref.current
288
- }
289
- }
@@ -0,0 +1,126 @@
1
+ import * as React from 'react'
2
+ import { pick, useLayoutEffect, usePrevious } from './utils'
3
+ import { useRouter } from './useRouter'
4
+ import { useRouterState } from './useRouterState'
5
+
6
+ export function Transitioner() {
7
+ const router = useRouter()
8
+ const mountLoadForRouter = React.useRef({ router, mounted: false })
9
+ const routerState = useRouterState({
10
+ select: (s) =>
11
+ pick(s, ['isLoading', 'location', 'resolvedLocation', 'isTransitioning']),
12
+ })
13
+
14
+ const [isTransitioning, startReactTransition_] = React.useTransition()
15
+ // Track pending state changes
16
+ const hasPendingMatches = useRouterState({
17
+ select: (s) => s.matches.some((d) => d.status === 'pending'),
18
+ })
19
+
20
+ const previousIsLoading = usePrevious(routerState.isLoading)
21
+
22
+ const isAnyPending =
23
+ routerState.isLoading || isTransitioning || hasPendingMatches
24
+ const previousIsAnyPending = usePrevious(isAnyPending)
25
+
26
+ router.startReactTransition = startReactTransition_
27
+
28
+ const tryLoad = async () => {
29
+ try {
30
+ await router.load()
31
+ } catch (err) {
32
+ console.error(err)
33
+ }
34
+ }
35
+
36
+ // Subscribe to location changes
37
+ // and try to load the new location
38
+ useLayoutEffect(() => {
39
+ const unsub = router.history.subscribe(router.load)
40
+
41
+ const nextLocation = router.buildLocation({
42
+ to: router.latestLocation.pathname,
43
+ search: true,
44
+ params: true,
45
+ hash: true,
46
+ state: true,
47
+ })
48
+
49
+ if (routerState.location.href !== nextLocation.href) {
50
+ router.commitLocation({ ...nextLocation, replace: true })
51
+ }
52
+
53
+ return () => {
54
+ unsub()
55
+ }
56
+ // eslint-disable-next-line react-hooks/exhaustive-deps
57
+ }, [router, router.history])
58
+
59
+ // Try to load the initial location
60
+ useLayoutEffect(() => {
61
+ if (
62
+ window.__TSR_DEHYDRATED__ ||
63
+ (mountLoadForRouter.current.router === router &&
64
+ mountLoadForRouter.current.mounted)
65
+ ) {
66
+ return
67
+ }
68
+ mountLoadForRouter.current = { router, mounted: true }
69
+ tryLoad()
70
+ // eslint-disable-next-line react-hooks/exhaustive-deps
71
+ }, [router])
72
+
73
+ useLayoutEffect(() => {
74
+ // The router was loading and now it's not
75
+ if (previousIsLoading && !routerState.isLoading) {
76
+ const toLocation = router.state.location
77
+ const fromLocation = router.state.resolvedLocation
78
+ const pathChanged = fromLocation.href !== toLocation.href
79
+
80
+ router.emit({
81
+ type: 'onLoad',
82
+ fromLocation,
83
+ toLocation,
84
+ pathChanged,
85
+ })
86
+
87
+ // if (router.viewTransitionPromise) {
88
+ // console.log('resolving view transition promise')
89
+ // }
90
+ // router.viewTransitionPromise?.resolve(true)
91
+ }
92
+ }, [previousIsLoading, router, routerState.isLoading])
93
+
94
+ useLayoutEffect(() => {
95
+ // The router was pending and now it's not
96
+ if (previousIsAnyPending && !isAnyPending) {
97
+ const toLocation = router.state.location
98
+ const fromLocation = router.state.resolvedLocation
99
+ const pathChanged = fromLocation.href !== toLocation.href
100
+
101
+ router.emit({
102
+ type: 'onResolved',
103
+ fromLocation,
104
+ toLocation,
105
+ pathChanged,
106
+ })
107
+
108
+ router.__store.setState((s) => ({
109
+ ...s,
110
+ status: 'idle',
111
+ resolvedLocation: s.location,
112
+ }))
113
+
114
+ if ((document as any).querySelector) {
115
+ if (router.state.location.hash !== '') {
116
+ const el = document.getElementById(router.state.location.hash)
117
+ if (el) {
118
+ el.scrollIntoView()
119
+ }
120
+ }
121
+ }
122
+ }
123
+ }, [isAnyPending, previousIsAnyPending, router])
124
+
125
+ return null
126
+ }
package/src/utils.ts CHANGED
@@ -352,3 +352,15 @@ export function removeLayoutSegments(routePath: string): string {
352
352
  const newSegments = segments.filter((segment) => !segment.startsWith('_'))
353
353
  return newSegments.join('/')
354
354
  }
355
+
356
+ export function usePrevious<T>(value: T): T {
357
+ const ref = React.useRef<T>(value)
358
+
359
+ if (ref.current !== value) {
360
+ const prevValue = ref.current
361
+ ref.current = value
362
+ return prevValue
363
+ } else {
364
+ return ref.current
365
+ }
366
+ }