Skip to content

Commit 980159a

Browse files
refactor(history): use TSR_key namespace in state for hash (#4356)
Co-authored-by: SeanCassiere <33615041+SeanCassiere@users.noreply.github.com>
1 parent 84f8f96 commit 980159a

File tree

9 files changed

+31
-16
lines changed

9 files changed

+31
-16
lines changed

docs/router/framework/react/api/router/ParsedHistoryStateType.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ The `ParsedHistoryState` type represents a parsed state object. Additionally to
77

88
```tsx
99
export type ParsedHistoryState = HistoryState & {
10-
key?: string
10+
key?: string // TODO: Remove in v2 - use __TSR_key instead
11+
__TSR_key?: string
1112
__TSR_index: number
1213
}
1314
```

docs/router/framework/react/guide/scroll-restoration.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,9 @@ Falling in behind Remix's own Scroll Restoration APIs, you can also customize th
7171

7272
The `getKey` option receives the relevant `Location` state from TanStack Router and expects you to return a string to uniquely identify the scrollable measurements for that state.
7373

74-
The default `getKey` is `(location) => location.state.key!`, where `key` is the unique key generated for each entry in the history.
74+
The default `getKey` is `(location) => location.state.__TSR_key!`, where `__TSR_key` is the unique key generated for each entry in the history.
75+
76+
> Older versions, prior to `v1.121.34`, used `state.key` as the default key, but this has been deprecated in favor of `state.__TSR_key`. For now, `location.state.key` will still be available for compatibility, but it will be removed in the next major version.
7577
7678
## Examples
7779

@@ -95,7 +97,7 @@ const router = createRouter({
9597
const paths = ['/', '/chat']
9698
return paths.includes(location.pathname)
9799
? location.pathname
98-
: location.state.key!
100+
: location.state.__TSR_key!
99101
},
100102
})
101103
```

packages/history/src/index.ts

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ export interface ParsedPath {
5353
export interface HistoryState {}
5454

5555
export type ParsedHistoryState = HistoryState & {
56-
key?: string
56+
key?: string // TODO: Remove in v2 - use __TSR_key instead
57+
__TSR_key?: string
5758
__TSR_index: number
5859
}
5960

@@ -252,9 +253,11 @@ function assignKeyAndIndex(index: number, state: HistoryState | undefined) {
252253
if (!state) {
253254
state = {} as HistoryState
254255
}
256+
const key = createRandomKey()
255257
return {
256258
...state,
257-
key: createRandomKey(),
259+
key, // TODO: Remove in v2 - use __TSR_key instead
260+
__TSR_key: key,
258261
[stateIndexKey]: index,
259262
} as ParsedHistoryState
260263
}
@@ -302,11 +305,13 @@ export function createBrowserHistory(opts?: {
302305
))
303306

304307
// Ensure there is always a key to start
305-
if (!win.history.state?.key) {
308+
if (!win.history.state?.__TSR_key && !win.history.state?.key) {
309+
const addedKey = createRandomKey()
306310
win.history.replaceState(
307311
{
308312
[stateIndexKey]: 0,
309-
key: createRandomKey(),
313+
key: addedKey, // TODO: Remove in v2 - use __TSR_key instead
314+
__TSR_key: addedKey,
310315
},
311316
'',
312317
)
@@ -615,6 +620,8 @@ export function parseHref(
615620
const hashIndex = href.indexOf('#')
616621
const searchIndex = href.indexOf('?')
617622

623+
const addedKey = createRandomKey()
624+
618625
return {
619626
href,
620627
pathname: href.substring(
@@ -632,7 +639,7 @@ export function parseHref(
632639
searchIndex > -1
633640
? href.slice(searchIndex, hashIndex === -1 ? undefined : hashIndex)
634641
: '',
635-
state: state || { [stateIndexKey]: 0, key: createRandomKey() },
642+
state: state || { [stateIndexKey]: 0, key: addedKey, __TSR_key: addedKey },
636643
}
637644
}
638645

packages/react-router/src/Match.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ export const Match = React.memo(function MatchImpl({
126126
// On Rendered can't happen above the root layout because it actually
127127
// renders a dummy dom element to track the rendered state of the app.
128128
// We render a script tag with a key that changes based on the current
129-
// location state.key. Also, because it's below the root layout, it
129+
// location state.__TSR_key. Also, because it's below the root layout, it
130130
// allows us to fire onRendered events even after a hydration mismatch
131131
// error that occurred above the root layout (like bad head/link tags,
132132
// which is common).
@@ -139,7 +139,7 @@ function OnRendered() {
139139

140140
return (
141141
<script
142-
key={router.latestLocation.state.key}
142+
key={router.latestLocation.state.__TSR_key}
143143
suppressHydrationWarning
144144
ref={(el) => {
145145
if (

packages/react-router/tests/redirect.test.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,7 @@ describe('redirect', () => {
364364
searchStr: '',
365365
state: {
366366
__TSR_index: 0,
367+
__TSR_key: currentRedirect.options._fromLocation!.state.__TSR_key,
367368
key: currentRedirect.options._fromLocation!.state.key,
368369
},
369370
},

packages/router-core/src/router.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1016,7 +1016,8 @@ export class RouterCore<
10161016
if (__tempLocation && (!__tempKey || __tempKey === this.tempLocationKey)) {
10171017
// Sync up the location keys
10181018
const parsedTempLocation = parse(__tempLocation) as any
1019-
parsedTempLocation.state.key = location.state.key
1019+
parsedTempLocation.state.key = location.state.key // TODO: Remove in v2 - use __TSR_key instead
1020+
parsedTempLocation.state.__TSR_key = location.state.__TSR_key
10201021

10211022
delete parsedTempLocation.state.__tempLocation
10221023

@@ -1616,7 +1617,8 @@ export class RouterCore<
16161617
// temporarily add the previous values to the next state so they don't affect
16171618
// the comparison
16181619
const ignoredProps = [
1619-
'key',
1620+
'key', // TODO: Remove in v2 - use __TSR_key instead
1621+
'__TSR_key',
16201622
'__TSR_index',
16211623
'__hashScrollIntoViewOptions',
16221624
] as const
@@ -1657,7 +1659,8 @@ export class RouterCore<
16571659
...nextHistory.state,
16581660
__tempKey: undefined!,
16591661
__tempLocation: undefined!,
1660-
key: undefined!,
1662+
__TSR_key: undefined!,
1663+
key: undefined!, // TODO: Remove in v2 - use __TSR_key instead
16611664
},
16621665
},
16631666
},

packages/router-core/src/scroll-restoration.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ export const scrollRestorationCache = createScrollRestorationCache()
7979
*/
8080

8181
export const defaultGetScrollRestorationKey = (location: ParsedLocation) => {
82-
return location.state.key! || location.href
82+
return location.state.__TSR_key! || location.href
8383
}
8484

8585
export function getCssSelector(el: any): string {

packages/solid-router/src/Match.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ export const Match = (props: { matchId: string }) => {
131131
// On Rendered can't happen above the root layout because it actually
132132
// renders a dummy dom element to track the rendered state of the app.
133133
// We render a script tag with a key that changes based on the current
134-
// location state.key. Also, because it's below the root layout, it
134+
// location state.__TSR_key. Also, because it's below the root layout, it
135135
// allows us to fire onRendered events even after a hydration mismatch
136136
// error that occurred above the root layout (like bad head/link tags,
137137
// which is common).
@@ -140,7 +140,7 @@ function OnRendered() {
140140

141141
const location = useRouterState({
142142
select: (s) => {
143-
return s.resolvedLocation?.state.key
143+
return s.resolvedLocation?.state.__TSR_key
144144
},
145145
})
146146
Solid.createEffect(

packages/solid-router/tests/redirect.test.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,7 @@ describe('redirect', () => {
358358
searchStr: '',
359359
state: {
360360
__TSR_index: 0,
361+
__TSR_key: currentRedirect.options._fromLocation!.state.__TSR_key,
361362
key: currentRedirect.options._fromLocation!.state.key,
362363
},
363364
},

0 commit comments

Comments
 (0)