-
Notifications
You must be signed in to change notification settings - Fork 41
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
…256) Co-authored-by: Marco Pasqualetti <[email protected]>
- Loading branch information
1 parent
d1b1217
commit d12d840
Showing
16 changed files
with
178 additions
and
224 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,22 +1,111 @@ | ||
import React from 'react' | ||
import { createContext, useState, useEffect, useContext, useMemo } from 'react' | ||
import type { ReactNode } from 'react' | ||
|
||
import type { Router } from '../router' | ||
import type { ServerRouterInfo } from '../types' | ||
|
||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion | ||
const routerContext = React.createContext<Router>(null!) | ||
export interface ParsedLocation { | ||
href: string | ||
pathname: string | ||
search: Record<string, string> | ||
searchStr: string | ||
hash: string | ||
} | ||
|
||
interface RouterContextValue { | ||
router: Router | ||
location: ParsedLocation | ||
updateLocation: (loc: ParsedLocation) => void | ||
} | ||
|
||
const TUONO_CONTEXT_GLOBAL_NAME = '__TUONO_CONTEXT__' | ||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion | ||
const RouterContext = createContext<RouterContextValue>(null!) | ||
|
||
export function getRouterContext(): React.Context<Router> { | ||
function getInitialLocation( | ||
serverSideProps?: ServerRouterInfo, | ||
): ParsedLocation { | ||
if (typeof document === 'undefined') { | ||
return routerContext | ||
return { | ||
pathname: serverSideProps?.pathname || '', | ||
hash: '', | ||
href: serverSideProps?.href || '', | ||
searchStr: serverSideProps?.searchStr || '', | ||
// TODO: Polyfill URLSearchParams | ||
search: {}, | ||
} | ||
} | ||
|
||
if (window[TUONO_CONTEXT_GLOBAL_NAME]) { | ||
return window[TUONO_CONTEXT_GLOBAL_NAME] | ||
const { location } = window | ||
return { | ||
pathname: location.pathname, | ||
hash: location.hash, | ||
href: location.href, | ||
searchStr: location.search, | ||
search: Object.fromEntries(new URLSearchParams(location.search)), | ||
} | ||
} | ||
|
||
interface RouterContextProviderProps { | ||
router: Router | ||
children: ReactNode | ||
serverSideProps?: ServerRouterInfo | ||
} | ||
|
||
window[TUONO_CONTEXT_GLOBAL_NAME] = routerContext | ||
export function RouterContextProvider({ | ||
router, | ||
children, | ||
serverSideProps, | ||
}: RouterContextProviderProps): ReactNode { | ||
// Allow the router to update options on the router instance | ||
router.update({ ...router.options } as Parameters<typeof router.update>[0]) | ||
|
||
const [location, setLocation] = useState<ParsedLocation>(() => | ||
getInitialLocation(serverSideProps), | ||
) | ||
|
||
/** | ||
* Listen browser navigation events | ||
*/ | ||
useEffect(() => { | ||
const updateLocationOnPopStateChange = ({ | ||
target, | ||
}: PopStateEvent): void => { | ||
const { location: targetLocation } = target as typeof window | ||
const { pathname, hash, href, search } = targetLocation | ||
|
||
setLocation({ | ||
pathname, | ||
hash, | ||
href, | ||
searchStr: search, | ||
search: Object.fromEntries(new URLSearchParams(search)), | ||
}) | ||
} | ||
|
||
window.addEventListener('popstate', updateLocationOnPopStateChange) | ||
|
||
return (): void => { | ||
window.removeEventListener('popstate', updateLocationOnPopStateChange) | ||
} | ||
}, []) | ||
|
||
const contextValue: RouterContextValue = useMemo( | ||
() => ({ | ||
router, | ||
location, | ||
updateLocation: setLocation, | ||
}), | ||
[location, router], | ||
) | ||
|
||
return ( | ||
<RouterContext.Provider value={contextValue}> | ||
{children} | ||
</RouterContext.Provider> | ||
) | ||
} | ||
|
||
return routerContext | ||
/** @warning DO NOT EXPORT THIS TO USER LAND */ | ||
export function useRouterContext(): RouterContextValue { | ||
return useContext(RouterContext) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,51 +1,32 @@ | ||
import React from 'react' | ||
import type { ReactNode, JSX } from 'react' | ||
import type { JSX } from 'react' | ||
import { Suspense } from 'react' | ||
|
||
import { useListenBrowserUrlUpdates } from '../hooks/useListenBrowserUrlUpdates' | ||
import { useInitRouterStore } from '../hooks/useRouterStore' | ||
import type { ServerProps } from '../types' | ||
import type { Router } from '../router' | ||
|
||
import { getRouterContext } from './RouterContext' | ||
import { RouterContextProvider } from './RouterContext' | ||
import { Matches } from './Matches' | ||
|
||
interface RouterContextProviderProps { | ||
router: Router | ||
children: ReactNode | ||
} | ||
|
||
function RouterContextProvider({ | ||
router, | ||
children, | ||
}: RouterContextProviderProps): JSX.Element { | ||
// Allow the router to update options on the router instance | ||
router.update({ ...router.options } as Parameters<typeof router.update>[0]) | ||
|
||
const routerContext = getRouterContext() | ||
|
||
return ( | ||
<React.Suspense> | ||
<routerContext.Provider value={router}>{children}</routerContext.Provider> | ||
</React.Suspense> | ||
) | ||
} | ||
|
||
interface RouterProviderProps { | ||
router: Router | ||
serverProps?: ServerProps | ||
} | ||
|
||
/** | ||
* This component is used in the tuono app entry point | ||
*/ | ||
export function RouterProvider({ | ||
router, | ||
serverProps, | ||
}: RouterProviderProps): JSX.Element { | ||
useInitRouterStore(serverProps) | ||
|
||
useListenBrowserUrlUpdates() | ||
|
||
return ( | ||
<RouterContextProvider router={router}> | ||
<Matches serverSideProps={serverProps?.props} /> | ||
</RouterContextProvider> | ||
<Suspense> | ||
<RouterContextProvider | ||
router={router} | ||
serverSideProps={serverProps?.router} | ||
> | ||
<Matches serverSideProps={serverProps?.props} /> | ||
</RouterContextProvider> | ||
</Suspense> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
34 changes: 0 additions & 34 deletions
34
packages/tuono-router/src/hooks/useListenBrowserUrlUpdates.tsx
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.