59 wiersze
1.6 KiB
TypeScript
59 wiersze
1.6 KiB
TypeScript
import React, { useEffect, useState } from "react";
|
|
import ReactDOM from "react-dom";
|
|
import { PageContext, PAGE_QUERY_ARG } from "./page";
|
|
import { pageNames, Pages, toPageName, DEFAULT_PAGE } from "./pages";
|
|
|
|
const APP_ID = "app";
|
|
|
|
const appEl = document.getElementById(APP_ID);
|
|
|
|
if (!appEl) {
|
|
throw new Error(`Unable to find #${APP_ID}!`);
|
|
}
|
|
|
|
function getWindowSearch(): URLSearchParams {
|
|
return new URLSearchParams(window.location.search);
|
|
}
|
|
|
|
/**
|
|
* Call the given handler whenever a `popstate` event
|
|
* occurs.
|
|
*
|
|
* Return a function that wraps `window.history.pushState()`;
|
|
* the given handler will be called immediately afterwards.
|
|
*/
|
|
function usePushState(onPushOrPopState: () => void) {
|
|
useEffect(() => {
|
|
window.addEventListener("popstate", onPushOrPopState);
|
|
return () => {
|
|
window.removeEventListener("popstate", onPushOrPopState);
|
|
};
|
|
}, [onPushOrPopState]);
|
|
|
|
return function pushState(href: string) {
|
|
window.history.pushState(null, "", href);
|
|
onPushOrPopState();
|
|
};
|
|
}
|
|
|
|
const App: React.FC<{}> = (props) => {
|
|
const [search, setSearch] = useState(getWindowSearch());
|
|
const updateSearchFromWindow = () => setSearch(getWindowSearch());
|
|
const currPage = toPageName(search.get(PAGE_QUERY_ARG) || "", DEFAULT_PAGE);
|
|
const PageComponent = Pages[currPage];
|
|
const pushState = usePushState(updateSearchFromWindow);
|
|
const ctx: PageContext = {
|
|
currPage,
|
|
allPages: pageNames,
|
|
pushState,
|
|
};
|
|
|
|
return (
|
|
<PageContext.Provider value={ctx}>
|
|
<PageComponent />
|
|
</PageContext.Provider>
|
|
);
|
|
};
|
|
|
|
ReactDOM.render(<App />, appEl);
|