Use history.pushState() for internal links.

pull/75/head
Atul Varma 2021-04-02 21:17:44 -04:00
rodzic b28a0114b9
commit a13f989ab3
2 zmienionych plików z 56 dodań i 7 usunięć

Wyświetl plik

@ -1,4 +1,4 @@
import React from "react";
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";
@ -11,13 +11,41 @@ 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 page = new URLSearchParams(window.location.search);
const currPage = toPageName(page.get(PAGE_QUERY_ARG) || "", DEFAULT_PAGE);
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 (

Wyświetl plik

@ -1,21 +1,42 @@
import React, { useContext } from "react";
import React, { MouseEvent, useContext } from "react";
import type { PageName } from "./pages";
export type PageContext = {
currPage: PageName;
allPages: PageName[];
pushState: (href: string) => void;
};
export const PageContext = React.createContext<PageContext>({
currPage: "vocabulary",
allPages: [],
pushState: () => {
throw new Error("No page context is defined!");
},
});
export const PAGE_QUERY_ARG = "p";
const PageLink: React.FC<{ page: PageName }> = ({ page }) => (
<a href={`?${PAGE_QUERY_ARG}=${encodeURIComponent(page)}`}>{page}</a>
);
function isNormalLinkClick(e: MouseEvent): boolean {
return !e.shiftKey && !e.altKey && !e.metaKey && !e.ctrlKey && e.button === 0;
}
const PageLink: React.FC<{ page: PageName }> = ({ page }) => {
const href = `?${PAGE_QUERY_ARG}=${encodeURIComponent(page)}`;
const { pushState } = useContext(PageContext);
const handleClick = (e: MouseEvent) => {
if (isNormalLinkClick(e)) {
pushState(href);
e.preventDefault();
}
};
return (
<a href={href} onClick={handleClick}>
{page}
</a>
);
};
const Navbar: React.FC<{}> = (props) => {
const pc = useContext(PageContext);