Skip to content

Commit 0f7d8c3

Browse files
brenelzbirkskyum
authored andcommitted
simplify the solution
1 parent 5461c31 commit 0f7d8c3

File tree

2 files changed

+75
-106
lines changed

2 files changed

+75
-106
lines changed

packages/router-core/src/router.ts

Lines changed: 67 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -118,22 +118,22 @@ export type RegisteredConfigType<TRegister, TKey> = TRegister extends {
118118
config: infer TConfig
119119
}
120120
? TConfig extends {
121-
'~types': infer TTypes
122-
}
123-
? TKey extends keyof TTypes
124-
? TTypes[TKey]
125-
: unknown
126-
: unknown
121+
'~types': infer TTypes
122+
}
123+
? TKey extends keyof TTypes
124+
? TTypes[TKey]
125+
: unknown
126+
: unknown
127127
: unknown
128128

129129
export type DefaultRemountDepsFn<TRouteTree extends AnyRoute> = (
130130
opts: MakeRemountDepsOptionsUnion<TRouteTree>,
131131
) => any
132132

133-
export interface DefaultRouterOptionsExtensions {}
133+
export interface DefaultRouterOptionsExtensions { }
134134

135135
export interface RouterOptionsExtensions
136-
extends DefaultRouterOptionsExtensions {}
136+
extends DefaultRouterOptionsExtensions { }
137137

138138
export type SSROption = boolean | 'data-only'
139139

@@ -423,8 +423,8 @@ export interface RouterOptions<
423423
* @default false
424424
*/
425425
scrollRestoration?:
426-
| boolean
427-
| ((opts: { location: ParsedLocation }) => boolean)
426+
| boolean
427+
| ((opts: { location: ParsedLocation }) => boolean)
428428

429429
/**
430430
* A function that will be called to get the key for the scroll restoration cache.
@@ -591,12 +591,12 @@ export type InferRouterContext<TRouteTree extends AnyRoute> =
591591

592592
export type RouterContextOptions<TRouteTree extends AnyRoute> =
593593
AnyContext extends InferRouterContext<TRouteTree>
594-
? {
595-
context?: InferRouterContext<TRouteTree>
596-
}
597-
: {
598-
context: InferRouterContext<TRouteTree>
599-
}
594+
? {
595+
context?: InferRouterContext<TRouteTree>
596+
}
597+
: {
598+
context: InferRouterContext<TRouteTree>
599+
}
600600

601601
export type RouterConstructorOptions<
602602
TRouteTree extends AnyRoute,
@@ -768,14 +768,14 @@ export type AnyRouter = RouterCore<any, any, any, any, any>
768768

769769
export interface ViewTransitionOptions {
770770
types:
771-
| Array<string>
772-
| ((locationChangeInfo: {
773-
fromLocation?: ParsedLocation
774-
toLocation: ParsedLocation
775-
pathChanged: boolean
776-
hrefChanged: boolean
777-
hashChanged: boolean
778-
}) => Array<string> | false)
771+
| Array<string>
772+
| ((locationChangeInfo: {
773+
fromLocation?: ParsedLocation
774+
toLocation: ParsedLocation
775+
pathChanged: boolean
776+
hrefChanged: boolean
777+
hashChanged: boolean
778+
}) => Array<string> | false)
779779
}
780780

781781
// TODO where is this used? can we remove this?
@@ -791,7 +791,7 @@ export function defaultSerializeError(err: unknown) {
791791
}
792792

793793
if (process.env.NODE_ENV === 'development') {
794-
;(obj as any).stack = err.stack
794+
; (obj as any).stack = err.stack
795795
}
796796

797797
return obj
@@ -838,12 +838,12 @@ export type CreateRouterFn = <
838838
options: undefined extends number
839839
? 'strictNullChecks must be enabled in tsconfig.json'
840840
: RouterConstructorOptions<
841-
TRouteTree,
842-
TTrailingSlashOption,
843-
TDefaultStructuralSharingOption,
844-
TRouterHistory,
845-
TDehydrated
846-
>,
841+
TRouteTree,
842+
TTrailingSlashOption,
843+
TDefaultStructuralSharingOption,
844+
TRouterHistory,
845+
TDehydrated
846+
>,
847847
) => RouterCore<
848848
TRouteTree,
849849
TTrailingSlashOption,
@@ -938,13 +938,6 @@ export class RouterCore<
938938
// router can be used in a non-react environment if necessary
939939
startTransition: StartTransitionFn = (fn) => fn()
940940

941-
/**
942-
* Can be overridden by framework implementations to wrap batch operations
943-
* in framework-specific transition APIs (e.g., Solid's startTransition).
944-
* This allows state updates to be wrapped without modifying the async flow.
945-
*/
946-
wrapBatch: (fn: () => void) => void = (fn) => fn()
947-
948941
isShell() {
949942
return !!this.options.isShell
950943
}
@@ -980,11 +973,11 @@ export class RouterCore<
980973

981974
this.pathParamsDecodeCharMap = this.options.pathParamsAllowedCharacters
982975
? new Map(
983-
this.options.pathParamsAllowedCharacters.map((char) => [
984-
encodeURIComponent(char),
985-
char,
986-
]),
987-
)
976+
this.options.pathParamsAllowedCharacters.map((char) => [
977+
encodeURIComponent(char),
978+
char,
979+
]),
980+
)
988981
: undefined
989982

990983
if (
@@ -1257,7 +1250,7 @@ export class RouterCore<
12571250
foundRoute
12581251
? foundRoute.path !== '/' && routeParams['**']
12591252
: // Or if we didn't find a route and we have left over path
1260-
trimPathRight(next.pathname)
1253+
trimPathRight(next.pathname)
12611254
) {
12621255
// If the user has defined an (old) 404 route, use it
12631256
if (this.options.notFoundRoute) {
@@ -1432,9 +1425,9 @@ export class RouterCore<
14321425
} else {
14331426
const status =
14341427
route.options.loader ||
1435-
route.options.beforeLoad ||
1436-
route.lazyFn ||
1437-
routeNeedsPreload(route)
1428+
route.options.beforeLoad ||
1429+
route.lazyFn ||
1430+
routeNeedsPreload(route)
14381431
? 'pending'
14391432
: 'success'
14401433

@@ -1652,9 +1645,9 @@ export class RouterCore<
16521645
: (dest.params ?? true) === true
16531646
? fromParams
16541647
: Object.assign(
1655-
fromParams,
1656-
functionalUpdate(dest.params as any, fromParams),
1657-
)
1648+
fromParams,
1649+
functionalUpdate(dest.params as any, fromParams),
1650+
)
16581651

16591652
// Interpolate the path first to get the actual resolved path, then match against that
16601653
const interpolatedNextTo = interpolatePath({
@@ -1851,7 +1844,7 @@ export class RouterCore<
18511844
'__hashScrollIntoViewOptions',
18521845
] as const
18531846
ignoredProps.forEach((prop) => {
1854-
;(next.state as any)[prop] = this.latestLocation.state[prop]
1847+
; (next.state as any)[prop] = this.latestLocation.state[prop]
18551848
})
18561849
const isEqual = deepEqual(next.state, this.latestLocation.state)
18571850
ignoredProps.forEach((prop) => {
@@ -1974,7 +1967,7 @@ export class RouterCore<
19741967
try {
19751968
new URL(`${href}`)
19761969
reloadDocument = true
1977-
} catch {}
1970+
} catch { }
19781971
}
19791972

19801973
if (reloadDocument) {
@@ -2107,7 +2100,7 @@ export class RouterCore<
21072100
let stayingMatches: Array<AnyRouteMatch> = []
21082101

21092102
// Wrap batch in framework-specific transition wrapper (e.g., Solid's startTransition)
2110-
this.wrapBatch(() => {
2103+
this.startTransition(() => {
21112104
batch(() => {
21122105
this.__store.setState((s) => {
21132106
const previousMatches = s.matches
@@ -2140,18 +2133,18 @@ export class RouterCore<
21402133
})
21412134
})
21422135

2143-
//
2144-
;(
2145-
[
2146-
[exitingMatches, 'onLeave'],
2147-
[enteringMatches, 'onEnter'],
2148-
[stayingMatches, 'onStay'],
2149-
] as const
2150-
).forEach(([matches, hook]) => {
2151-
matches.forEach((match) => {
2152-
this.looseRoutesById[match.routeId]!.options[hook]?.(match)
2136+
//
2137+
; (
2138+
[
2139+
[exitingMatches, 'onLeave'],
2140+
[enteringMatches, 'onEnter'],
2141+
[stayingMatches, 'onStay'],
2142+
] as const
2143+
).forEach(([matches, hook]) => {
2144+
matches.forEach((match) => {
2145+
this.looseRoutesById[match.routeId]!.options[hook]?.(match)
2146+
})
21532147
})
2154-
})
21552148
})
21562149
},
21572150
})
@@ -2246,11 +2239,11 @@ export class RouterCore<
22462239
const resolvedViewTransitionTypes =
22472240
typeof shouldViewTransition.types === 'function'
22482241
? shouldViewTransition.types(
2249-
getLocationChangeInfo({
2250-
resolvedLocation: prevLocation,
2251-
location: next,
2252-
}),
2253-
)
2242+
getLocationChangeInfo({
2243+
resolvedLocation: prevLocation,
2244+
location: next,
2245+
}),
2246+
)
22542247
: shouldViewTransition.types
22552248

22562249
if (resolvedViewTransitionTypes === false) {
@@ -2479,9 +2472,9 @@ export class RouterCore<
24792472
...location,
24802473
to: location.to
24812474
? this.resolvePathWithBase(
2482-
(location.from || '') as string,
2483-
location.to as string,
2484-
)
2475+
(location.from || '') as string,
2476+
location.to as string,
2477+
)
24852478
: undefined,
24862479
params: location.params || {},
24872480
leaveParams: true,
@@ -2540,10 +2533,10 @@ export class RouterCore<
25402533
}
25412534

25422535
/** Error thrown when search parameter validation fails. */
2543-
export class SearchParamError extends Error {}
2536+
export class SearchParamError extends Error { }
25442537

25452538
/** Error thrown when path parameter parsing/validation fails. */
2546-
export class PathParamError extends Error {}
2539+
export class PathParamError extends Error { }
25472540

25482541
const normalize = (str: string) =>
25492542
str.endsWith('/') && str.length > 1 ? str.slice(0, -1) : str

packages/solid-router/src/Transitioner.tsx

Lines changed: 8 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -35,39 +35,15 @@ export function Transitioner() {
3535
const isPagePending = () => isLoading() || hasPendingMatches()
3636
const previousIsPagePending = usePrevious(isPagePending)
3737

38-
// Wrap batch operations with Solid's startTransition
39-
// This ensures state updates that trigger re-renders happen within a transition,
40-
// which prevents Suspense boundaries from showing fallbacks immediately
41-
router.wrapBatch = (fn: () => void) => {
42-
// Only use startTransition if we're in a real browser (not jsdom) AND transitioning
43-
// Check for window.navigator.userAgent to distinguish real browser from jsdom test environment
44-
const isRealBrowser =
45-
typeof window !== 'undefined' &&
46-
typeof window.navigator !== 'undefined' &&
47-
typeof window.navigator.userAgent === 'string' &&
48-
!window.navigator.userAgent.includes('jsdom')
49-
50-
if (isRealBrowser && !router.isServer && isTransitioning()) {
51-
// Solid's startTransition executes the callback synchronously
52-
// but marks state updates as transitions
53-
Solid.startTransition(() => {
54-
fn()
55-
})
56-
} else {
57-
// Fallback for SSR/tests/non-transitions: execute directly
58-
fn()
59-
}
60-
}
61-
62-
// Track transitioning state but don't wrap the async work in startTransition
63-
// The wrapBatch hook above handles wrapping the state updates
64-
router.startTransition = async (fn: () => void | Promise<void>) => {
38+
router.startTransition = (fn: () => void | Promise<void>) => {
6539
setIsTransitioning(true)
66-
try {
67-
await fn()
68-
} finally {
69-
setIsTransitioning(false)
70-
}
40+
Solid.startTransition(async () => {
41+
try {
42+
await fn()
43+
} finally {
44+
setIsTransitioning(false)
45+
}
46+
})
7147
}
7248

7349
// Subscribe to location changes

0 commit comments

Comments
 (0)