Files
tuono/packages/tuono-router/src/components/RouterProvider.tsx
T
2024-05-23 20:41:05 +02:00

87 lines
1.9 KiB
TypeScript

import { getRouterContext } from './RouterContext'
import { Matches } from './Matches'
import { useRouterStore } from '../hooks/useRouterStore'
import React, { useLayoutEffect, type ReactNode } from 'react'
type Router = any
interface RouterContextProviderProps {
router: Router
children: ReactNode
}
function RouterContextProvider({
router,
children,
...rest
}: RouterContextProviderProps): JSX.Element {
// Allow the router to update options on the router instance
router.update({
...router.options,
...rest,
context: {
...router.options.context,
...rest.context,
},
})
const routerContext = getRouterContext()
const pendingElement = router.options.defaultPendingComponent ? (
<router.options.defaultPendingComponent />
) : null
return (
<React.Suspense fallback={pendingElement}>
<routerContext.Provider value={router}>{children}</routerContext.Provider>
</React.Suspense>
)
}
interface RouterProviderProps {
router: Router
serverProps?: ServerProps
}
interface ServerProps {
router: Location
props: any
}
const initRouterStore = (props?: ServerProps): void => {
const updateLocation = useRouterStore((st) => st.updateLocation)
if (typeof window === 'undefined') {
updateLocation({
pathname: props?.router.pathname || '',
hash: '',
href: '',
searchStr: '',
})
}
useLayoutEffect(() => {
const { pathname, hash, href, search } = window.location
updateLocation({
pathname,
hash,
href,
searchStr: search,
search: new URLSearchParams(search),
})
}, [])
}
export function RouterProvider({
router,
serverProps,
}: RouterProviderProps): JSX.Element {
initRouterStore(serverProps)
return (
<RouterContextProvider router={router}>
<Matches serverSideProps={serverProps?.props} />
</RouterContextProvider>
)
}