@tanstack/react-router 1.168.4 → 1.168.6

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.
@@ -3570,7 +3570,7 @@ The \`useBlocker\` hook accepts a single _required_ argument, an option object:
3570
3570
  - Think of this function as telling the router if it should block the navigation, so returning \`true\` mean that it should block the navigation and \`false\` meaning that it should be allowed
3571
3571
 
3572
3572
  \`\`\`ts
3573
- interface ShouldBlockFnLocation<...> {
3573
+ type ShouldBlockFnLocation<...> = {
3574
3574
  routeId: TRouteId
3575
3575
  fullPath: TFullPath
3576
3576
  pathname: string
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/react-router",
3
- "version": "1.168.4",
3
+ "version": "1.168.6",
4
4
  "description": "Modern and scalable routing for React applications",
5
5
  "author": "Tanner Linsley",
6
6
  "license": "MIT",
@@ -80,7 +80,7 @@
80
80
  "@tanstack/react-store": "^0.9.3",
81
81
  "isbot": "^5.1.22",
82
82
  "@tanstack/history": "1.161.6",
83
- "@tanstack/router-core": "1.168.4"
83
+ "@tanstack/router-core": "1.168.5"
84
84
  },
85
85
  "devDependencies": {
86
86
  "@testing-library/jest-dom": "^6.6.3",
package/src/Match.tsx CHANGED
@@ -17,11 +17,8 @@ import { SafeFragment } from './SafeFragment'
17
17
  import { renderRouteNotFound } from './renderRouteNotFound'
18
18
  import { ScrollRestoration } from './scroll-restoration'
19
19
  import { ClientOnly } from './ClientOnly'
20
- import type {
21
- AnyRoute,
22
- ParsedLocation,
23
- RootRouteOptions,
24
- } from '@tanstack/router-core'
20
+ import { useLayoutEffect } from './utils'
21
+ import type { AnyRoute, RootRouteOptions } from '@tanstack/router-core'
25
22
 
26
23
  export const Match = React.memo(function MatchImpl({
27
24
  matchId,
@@ -202,53 +199,52 @@ function MatchView({
202
199
  </ResolvedCatchBoundary>
203
200
  </ResolvedSuspenseBoundary>
204
201
  </matchContext.Provider>
205
- {matchState.parentRouteId === rootRouteId &&
206
- router.options.scrollRestoration ? (
202
+ {matchState.parentRouteId === rootRouteId ? (
207
203
  <>
208
- <OnRendered />
209
- <ScrollRestoration />
204
+ <OnRendered resetKey={resetKey} />
205
+ {router.options.scrollRestoration && (isServer ?? router.isServer) ? (
206
+ <ScrollRestoration />
207
+ ) : null}
210
208
  </>
211
209
  ) : null}
212
210
  </ShellComponent>
213
211
  )
214
212
  }
215
213
 
216
- // On Rendered can't happen above the root layout because it actually
217
- // renders a dummy dom element to track the rendered state of the app.
218
- // We render a script tag with a key that changes based on the current
219
- // location state.__TSR_key. Also, because it's below the root layout, it
220
- // allows us to fire onRendered events even after a hydration mismatch
221
- // error that occurred above the root layout (like bad head/link tags,
222
- // which is common).
223
- function OnRendered() {
214
+ // On Rendered can't happen above the root layout because it needs to run after
215
+ // the route subtree has committed below the root layout. Keeping it here lets
216
+ // us fire onRendered even after a hydration mismatch above the root layout
217
+ // (like bad head/link tags, which is common).
218
+ function OnRendered({ resetKey }: { resetKey: number }) {
224
219
  const router = useRouter()
225
220
 
226
- const prevLocationRef = React.useRef<undefined | ParsedLocation<{}>>(
227
- undefined,
228
- )
221
+ if (isServer ?? router.isServer) {
222
+ return null
223
+ }
229
224
 
230
- return (
231
- <script
232
- key={router.latestLocation.state.__TSR_key}
233
- suppressHydrationWarning
234
- ref={(el) => {
235
- if (
236
- el &&
237
- (prevLocationRef.current === undefined ||
238
- prevLocationRef.current.href !== router.latestLocation.href)
239
- ) {
240
- router.emit({
241
- type: 'onRendered',
242
- ...getLocationChangeInfo(
243
- router.stores.location.state,
244
- router.stores.resolvedLocation.state,
245
- ),
246
- })
247
- prevLocationRef.current = router.latestLocation
248
- }
249
- }}
250
- />
251
- )
225
+ // eslint-disable-next-line react-hooks/rules-of-hooks
226
+ const prevHrefRef = React.useRef<string | undefined>(undefined)
227
+
228
+ // eslint-disable-next-line react-hooks/rules-of-hooks
229
+ useLayoutEffect(() => {
230
+ const currentHref = router.latestLocation.href
231
+
232
+ if (
233
+ prevHrefRef.current === undefined ||
234
+ prevHrefRef.current !== currentHref
235
+ ) {
236
+ router.emit({
237
+ type: 'onRendered',
238
+ ...getLocationChangeInfo(
239
+ router.stores.location.state,
240
+ router.stores.resolvedLocation.state,
241
+ ),
242
+ })
243
+ prevHrefRef.current = currentHref
244
+ }
245
+ }, [router.latestLocation.state.__TSR_key, resetKey, router])
246
+
247
+ return null
252
248
  }
253
249
 
254
250
  export const MatchInner = React.memo(function MatchInnerImpl({
@@ -1,7 +1,5 @@
1
1
  import {
2
- defaultGetScrollRestorationKey,
3
- getCssSelector,
4
- scrollRestorationCache,
2
+ getElementScrollRestorationEntry,
5
3
  setupScrollRestoration,
6
4
  } from '@tanstack/router-core'
7
5
  import { useRouter } from './useRouter'
@@ -47,23 +45,5 @@ export function useElementScrollRestoration(
47
45
  ): ScrollRestorationEntry | undefined {
48
46
  useScrollRestoration()
49
47
 
50
- const router = useRouter()
51
- const getKey = options.getKey || defaultGetScrollRestorationKey
52
-
53
- let elementSelector = ''
54
-
55
- if (options.id) {
56
- elementSelector = `[data-scroll-restoration-id="${options.id}"]`
57
- } else {
58
- const element = options.getElement?.()
59
- if (!element) {
60
- return
61
- }
62
- elementSelector =
63
- element instanceof Window ? 'window' : getCssSelector(element)
64
- }
65
-
66
- const restoreKey = getKey(router.latestLocation)
67
- const byKey = scrollRestorationCache?.state[restoreKey]
68
- return byKey?.[elementSelector]
48
+ return getElementScrollRestorationEntry(useRouter(), options)
69
49
  }
@@ -1,45 +1,14 @@
1
- import {
2
- defaultGetScrollRestorationKey,
3
- escapeHtml,
4
- restoreScroll,
5
- storageKey,
6
- } from '@tanstack/router-core'
7
- import { isServer } from '@tanstack/router-core/isServer'
1
+ import { getScrollRestorationScriptForRouter } from '@tanstack/router-core/scroll-restoration-script'
8
2
  import { useRouter } from './useRouter'
9
3
  import { ScriptOnce } from './ScriptOnce'
10
4
 
11
5
  export function ScrollRestoration() {
12
6
  const router = useRouter()
13
- if (!router.isScrollRestoring || !(isServer ?? router.isServer)) {
14
- return null
15
- }
16
- if (typeof router.options.scrollRestoration === 'function') {
17
- const shouldRestore = router.options.scrollRestoration({
18
- location: router.latestLocation,
19
- })
20
- if (!shouldRestore) {
21
- return null
22
- }
23
- }
24
- const getKey =
25
- router.options.getScrollRestorationKey || defaultGetScrollRestorationKey
26
- const userKey = getKey(router.latestLocation)
27
- const resolvedKey =
28
- userKey !== defaultGetScrollRestorationKey(router.latestLocation)
29
- ? userKey
30
- : undefined
7
+ const script = getScrollRestorationScriptForRouter(router)
31
8
 
32
- const restoreScrollOptions: Parameters<typeof restoreScroll>[0] = {
33
- storageKey,
34
- shouldScrollRestoration: true,
35
- }
36
- if (resolvedKey) {
37
- restoreScrollOptions.key = resolvedKey
9
+ if (!script) {
10
+ return null
38
11
  }
39
12
 
40
- return (
41
- <ScriptOnce
42
- children={`(${restoreScroll.toString()})(${escapeHtml(JSON.stringify(restoreScrollOptions))})`}
43
- />
44
- )
13
+ return <ScriptOnce children={script} />
45
14
  }
@@ -12,12 +12,12 @@ import type {
12
12
  RegisteredRouter,
13
13
  } from '@tanstack/router-core'
14
14
 
15
- interface ShouldBlockFnLocation<
15
+ type ShouldBlockFnLocation<
16
16
  out TRouteId,
17
17
  out TFullPath,
18
18
  out TAllParams,
19
19
  out TFullSearchSchema,
20
- > {
20
+ > = {
21
21
  routeId: TRouteId
22
22
  fullPath: TFullPath
23
23
  pathname: string