diff --git a/client/BrowserRouter.tsx b/client/BrowserRouter.tsx index 352356a..1f9bf31 100644 --- a/client/BrowserRouter.tsx +++ b/client/BrowserRouter.tsx @@ -82,14 +82,18 @@ export const BrowserRouter: React.FC = ({ }, [currentHistory]) return ( - - + + - - + + ) } diff --git a/client/KeyworkPatternToPageComponent.tsx b/client/KeyworkPatternToPageComponent.tsx index a2e8f42..c0a5176 100644 --- a/client/KeyworkPatternToPageComponent.tsx +++ b/client/KeyworkPatternToPageComponent.tsx @@ -13,19 +13,20 @@ */ import { useMemo } from 'react' +import { useRequest } from '../http/RequestContext.js' import { PatternRouteComponentMap, RoutePatternsProps, URLPatternResultContext } from '../uri/index.js' import { useSSRPropsByPath } from './SSRPropsProvider.js' -import { useLocation } from './hooks.js' /** * @beta * @ignore */ export const KeyworkPatternToPageComponent: React.FC = ({ routes }) => { - const location = useLocation() + const request = useRequest() + const staticPropsByPath = useSSRPropsByPath() const patternRouteComponentMap = useMemo(() => new PatternRouteComponentMap(routes), [routes]) - const result = useMemo(() => patternRouteComponentMap.match(location), [location, patternRouteComponentMap]) + const result = useMemo(() => patternRouteComponentMap.match(request.url), [patternRouteComponentMap, request.url]) if (!result) { return diff --git a/client/SSRPropsProvider.tsx b/client/SSRPropsProvider.tsx index e7f4e8b..10962cc 100644 --- a/client/SSRPropsProvider.tsx +++ b/client/SSRPropsProvider.tsx @@ -15,7 +15,6 @@ import { createContext, useCallback, useContext, useEffect, useRef, useState } from 'react' import { useKeyworkLogger } from '../logging/index.js' import { KEYWORK_STATIC_PROPS_QUERY_KEY } from '../uri/index.js' -import { useLocation } from './hooks.js' /** * A mapping of static props to a given path. @@ -30,21 +29,24 @@ export const useSSRPropsByPath = () => useContext(SSRPropsContext) export interface SSRPropsProviderProps { initialPropsByPath: SSRPropsByPath initialLocation: URL + currentLocation?: Location children: React.ReactNode } export const SSRPropsProvider: React.FC = ({ initialPropsByPath, initialLocation, + currentLocation, children, }) => { const lastRenderLocationRef = useRef(initialLocation) const [propsByPath, setPropsByPath] = useState(initialPropsByPath) - const location = useLocation() const logger = useKeyworkLogger() const fetchRouteData = useCallback(async () => { - const url = new URL(location.pathname, (globalThis as any).location.origin) + if (!currentLocation) return + + const url = new URL(currentLocation.pathname, (globalThis as any).location.origin) url.searchParams.set(KEYWORK_STATIC_PROPS_QUERY_KEY, 'true') const response = await fetch(url) @@ -57,15 +59,16 @@ export const SSRPropsProvider: React.FC = ({ const data = await response.json() - setPropsByPath(new Map([[location.pathname, data]])) - }, [location.pathname, logger]) + setPropsByPath(new Map([[currentLocation.pathname, data]])) + }, [currentLocation, logger]) useEffect(() => { - if (lastRenderLocationRef.current.pathname !== location.pathname) { - lastRenderLocationRef.current = new URL(location.pathname, lastRenderLocationRef.current.origin) + if (!currentLocation) return + if (lastRenderLocationRef.current.pathname !== currentLocation.pathname) { + lastRenderLocationRef.current = new URL(currentLocation.pathname, lastRenderLocationRef.current.origin) fetchRouteData() } - }, [fetchRouteData, location]) + }, [currentLocation, fetchRouteData]) return {children} } diff --git a/client/hooks.ts b/client/hooks.ts index 6b57443..b608b9e 100644 --- a/client/hooks.ts +++ b/client/hooks.ts @@ -14,7 +14,7 @@ import { useEffect, useState } from 'react' export function useLocation() { - const [currentLocation, setCurrentLocation] = useState(location) + const [currentLocation, setCurrentLocation] = useState(location) useEffect(() => { const popStateHandler = (_event: PopStateEvent) => { diff --git a/package.json b/package.json index f8ef5ed..6099ff9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "keywork", - "version": "8.1.17", + "version": "8.1.19", "license": "AGPL-3.0", "author": "Teffen Ellis ", "description": "A batteries-included, magic-free, library for building web apps in V8 Isolates.", diff --git a/ssr/RequestDocument.tsx b/ssr/RequestDocument.tsx index e63f2e4..300c50d 100644 --- a/ssr/RequestDocument.tsx +++ b/ssr/RequestDocument.tsx @@ -59,16 +59,16 @@ export const RequestDocument: React.FC = ({ const initialPropsByPath: SSRPropsByPath = new Map([[initialNavigatorURL.pathname, staticProps]]) const appDocument = ( - - + + {pageElement} - - + + ) return appDocument diff --git a/uri/URLPattern.ts b/uri/URLPattern.ts index 6248a61..56d4425 100644 --- a/uri/URLPattern.ts +++ b/uri/URLPattern.ts @@ -115,12 +115,12 @@ interface NormalizeURLPatternOptions { export function normalizeURLPatternInput(patternLike: URLPatternLike): URLPatternInput { if (!patternLike) throw new KeyworkResourceError('`patternLike` must be defined') + if (patternLike instanceof URL) return patternLike + if (isURLPathname(patternLike)) return URLPathnameToURLPatternInput(patternLike) if (isKeyworkRouteComponent(patternLike)) return normalizeURLPattern(patternLike.pathname!) - if (patternLike instanceof URL) return patternLike - return patternLike } diff --git a/uri/URLPatternRouteMap.ts b/uri/URLPatternRouteMap.ts index af351d6..3e6c54e 100644 --- a/uri/URLPatternRouteMap.ts +++ b/uri/URLPatternRouteMap.ts @@ -16,9 +16,11 @@ import { IURLPattern, KeyworkRouteComponent, URLPathnameInput, + URLPatternLike, URLPatternResult, isKeyworkRouteComponent, normalizeURLPattern, + normalizeURLPatternInput, } from './URLPattern.js' export type RoutePatternEntry = [string, KeyworkRouteComponent] @@ -81,10 +83,11 @@ export class PatternRouteComponentMap extends Map