improved url entanglement with PageState (#15)

This commit is contained in:
Johannes Kirschbauer 2023-01-25 10:28:22 +01:00 committed by GitHub
parent 8679af38a2
commit 799cf175a0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 40 additions and 23 deletions

View File

@ -1,5 +1,5 @@
import React, { useState } from "react";
import { useRouter } from "next/router";
import { NextRouter, useRouter } from "next/router";
import {
InitialPageState,
initialPageState,
@ -13,8 +13,9 @@ type PageContextType = {
resetQueries: () => void;
};
const initialState = { ...initialPageState, FOTD: true };
export const PageContext = React.createContext<PageContextType>({
pageState: { ...initialPageState, FOTD: true },
pageState: initialState,
setPageState: () => {},
resetQueries: () => {},
setPageStateVariable: function a<T>() {
@ -31,31 +32,47 @@ export type SetPageStateVariable = <T>(
field: keyof InitialPageState
) => (value: React.SetStateAction<T> | T) => void;
const paramList: Omit<keyof PageState, "data">[] = [
"filter",
"selected",
"term",
"page",
"itemsPerPage",
];
const isQueryParam = (key: keyof PageState) => paramList.includes(key);
const isInitial = (key: keyof PageState, value: PageState[keyof PageState]) =>
JSON.stringify(initialState[key]) === JSON.stringify(value);
const updateRouter = (router: NextRouter, state: PageState) => {
const query = Object.entries(state)
.filter(([k]) => isQueryParam(k as keyof PageState))
.filter(([k, v]) => !isInitial(k as keyof PageState, v))
.reduce((acc, [k, v]) => {
return { ...acc, [k]: JSON.stringify(v) };
}, {});
router.push({ query });
};
export const PageContextProvider = (props: PageContextProviderProps) => {
const router = useRouter();
const { children, pageProps } = props;
const [pageState, setPageState] = useState<PageState>(pageProps);
function setPageStateVariable<T>(field: keyof InitialPageState) {
return function (value: React.SetStateAction<T> | T) {
{
if (typeof value !== "function") {
setPageState((curr) => {
const query = router.query;
query[field] = JSON.stringify(value);
router.push({ query });
return { ...curr, [field]: value };
});
} else {
const setter = value as Function;
setPageState((curr) => {
const query = router.query;
const newValue = setter(curr[field]);
query[field] = JSON.stringify(newValue);
router.push({ query });
return { ...curr, [field]: newValue };
});
}
if (typeof value !== "function") {
setPageState((curr) => {
const newState = { ...curr, [field]: value };
updateRouter(router, newState);
return newState;
});
} else {
const setter = value as Function;
setPageState((curr) => {
const newValue = setter(curr[field]);
const newState = { ...curr, [field]: newValue };
updateRouter(router, newState);
return { ...curr, [field]: newValue };
});
}
};
}

View File

@ -46,7 +46,7 @@ export default function FunctionsPage() {
const router = useRouter();
const [initialProps, setInitialProps] = useState<PageState | null>(null);
useEffect(() => {
if (router.isReady) {
if (router.isReady && initialProps === null) {
getInitialProps(router).then((r) => {
const { props } = r;
console.info("Url Query changed\n\nUpdating pageState with delta:", {
@ -55,7 +55,7 @@ export default function FunctionsPage() {
setInitialProps((curr) => ({ ...curr, ...props }));
});
}
}, [router]);
}, [router, initialProps]);
return (
<>
{!initialProps ? (