@@ -56,14 +56,16 @@ export function RouterProvider({
56
56
fallbackElement,
57
57
router,
58
58
} : RouterProviderProps ) : React . ReactElement {
59
+ let getState = React . useCallback ( ( ) => router . state , [ router ] ) ;
60
+
59
61
// Sync router state to our component state to force re-renders
60
62
let state : RouterState = useSyncExternalStoreShim (
61
63
router . subscribe ,
62
- ( ) => router . state ,
64
+ getState ,
63
65
// We have to provide this so React@18 doesn't complain during hydration,
64
66
// but we pass our serialized hydration data into the router so state here
65
67
// is already synced with what the server saw
66
- ( ) => router . state
68
+ getState
67
69
) ;
68
70
69
71
let navigator = React . useMemo ( ( ) : Navigator => {
@@ -87,6 +89,16 @@ export function RouterProvider({
87
89
88
90
let basename = router . basename || "/" ;
89
91
92
+ let dataRouterContext = React . useMemo (
93
+ ( ) => ( {
94
+ router,
95
+ navigator,
96
+ static : false ,
97
+ basename,
98
+ } ) ,
99
+ [ router , navigator , basename ]
100
+ ) ;
101
+
90
102
// The fragment and {null} here are important! We need them to keep React 18's
91
103
// useId happy when we are server-rendering since we may have a <script> here
92
104
// containing the hydrated server-side staticContext (from StaticRouterProvider).
@@ -95,15 +107,7 @@ export function RouterProvider({
95
107
// we don't need the <script> tag
96
108
return (
97
109
< >
98
- < DataRouterContext . Provider
99
- value = { {
100
- router,
101
- navigator,
102
- static : false ,
103
- // Do we need this?
104
- basename,
105
- } }
106
- >
110
+ < DataRouterContext . Provider value = { dataRouterContext } >
107
111
< DataRouterStateContext . Provider value = { state } >
108
112
< Router
109
113
basename = { router . basename }
@@ -330,39 +334,39 @@ export function Router({
330
334
key = "default" ,
331
335
} = locationProp ;
332
336
333
- let location = React . useMemo ( ( ) => {
337
+ let locationContext = React . useMemo ( ( ) => {
334
338
let trailingPathname = stripBasename ( pathname , basename ) ;
335
339
336
340
if ( trailingPathname == null ) {
337
341
return null ;
338
342
}
339
343
340
344
return {
341
- pathname : trailingPathname ,
342
- search,
343
- hash,
344
- state,
345
- key,
345
+ location : {
346
+ pathname : trailingPathname ,
347
+ search,
348
+ hash,
349
+ state,
350
+ key,
351
+ } ,
352
+ navigationType,
346
353
} ;
347
- } , [ basename , pathname , search , hash , state , key ] ) ;
354
+ } , [ basename , pathname , search , hash , state , key , navigationType ] ) ;
348
355
349
356
warning (
350
- location != null ,
357
+ locationContext != null ,
351
358
`<Router basename="${ basename } "> is not able to match the URL ` +
352
359
`"${ pathname } ${ search } ${ hash } " because it does not start with the ` +
353
360
`basename, so the <Router> won't render anything.`
354
361
) ;
355
362
356
- if ( location == null ) {
363
+ if ( locationContext == null ) {
357
364
return null ;
358
365
}
359
366
360
367
return (
361
368
< NavigationContext . Provider value = { navigationContext } >
362
- < LocationContext . Provider
363
- children = { children }
364
- value = { { location, navigationType } }
365
- />
369
+ < LocationContext . Provider children = { children } value = { locationContext } />
366
370
</ NavigationContext . Provider >
367
371
) ;
368
372
}
0 commit comments