Created
February 18, 2023 12:54
-
-
Save molefrog/70ad57db1acf689b3f4eaf77b7065233 to your computer and use it in GitHub Desktop.
wouter@2.10.0 SSR workaround
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
import { useSyncExternalStore } from "react"; | |
import { navigate } from "wouter/use-location"; | |
/** | |
* A temporary workaround for wouter@2.10.0 to fix server-side rendering | |
* Usage (note: the code is the same for client and server) | |
* | |
* import { createLocationHookSSR } from "wouter/use-location" | |
* | |
* const hook = createLocationHookSSR(url.pathname) // this argument is only used on the server | |
* | |
* <Router hook={hook}>Your app!</Router> | |
*/ | |
interface LocationOptions { | |
base?: string; | |
} | |
/** | |
* Location hook factory that accepts current path on the server side | |
*/ | |
export const createLocationHookSSR = (serverSidePath: string) => { | |
const useCurrentPathnameSSR = () => | |
useSyncExternalStore( | |
subscribeToLocationUpdates, | |
() => location.pathname, | |
() => serverSidePath // this was missing | |
); | |
return (opts: LocationOptions = {}) => [ | |
relativePath(opts.base, useCurrentPathnameSSR()), | |
(to, navOpts) => navigate(absolutePath(to, opts.base), navOpts), | |
]; | |
}; | |
/** | |
* The following methods are copied from wouter/use-location, there is no way to import them (yet!) | |
*/ | |
const eventPopstate = "popstate"; | |
const eventPushState = "pushState"; | |
const eventReplaceState = "replaceState"; | |
const eventHashchange = "hashchange"; | |
export const events = [eventPopstate, eventPushState, eventReplaceState, eventHashchange]; | |
const subscribeToLocationUpdates = (callback) => { | |
for (const event of events) { | |
addEventListener(event, callback); | |
} | |
return () => { | |
for (const event of events) { | |
removeEventListener(event, callback); | |
} | |
}; | |
}; | |
const relativePath = (base = "", path = location.pathname) => | |
!path.toLowerCase().indexOf(base.toLowerCase()) ? path.slice(base.length) || "/" : "~" + path; | |
const absolutePath = (to, base = "") => (to[0] === "~" ? to.slice(1) : base + to); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment