diff --git a/src/app/ColorSchemeInjector.tsx b/src/app/ColorSchemeInjector.tsx index cb8347fc..1bd24dc7 100644 --- a/src/app/ColorSchemeInjector.tsx +++ b/src/app/ColorSchemeInjector.tsx @@ -7,7 +7,6 @@ import { COLOR_SCHEME_LIGHT, DARK_MODE_STORAGE_KEY, } from "~/lib/constants" -import { getStorage } from "~/lib/storage" export const ColorSchemeInjector = () => { useServerInsertedHTML(() => { @@ -16,7 +15,14 @@ export const ColorSchemeInjector = () => { dangerouslySetInnerHTML={{ __html: `(() => { var DARK_MODE_STORAGE_KEY = "${DARK_MODE_STORAGE_KEY}"; -var getStorage = ${getStorage.toString()}; +var namespace = "xlog" +var getStorage = () => { + const data = {} + try { + data = JSON.parse(localStorage.getItem(namespace) || "{}") + } catch (error) {} + return data +} var COLOR_SCHEME_LIGHT = "${COLOR_SCHEME_LIGHT}"; var COLOR_SCHEME_DARK = "${COLOR_SCHEME_DARK}"; diff --git a/src/app/providers.tsx b/src/app/providers.tsx index 121c0816..72ae562b 100644 --- a/src/app/providers.tsx +++ b/src/app/providers.tsx @@ -34,6 +34,7 @@ const colorScheme: NotificationModalColorScheme = { border: `var(--border-color)`, } +const createQueryClient = () => new QueryClient() export default function Providers({ children, lang, @@ -45,7 +46,7 @@ export default function Providers({ useMobileLayout() useNProgress() - const [queryClient] = useState(() => new QueryClient()) + const [queryClient] = useState(createQueryClient) return ( diff --git a/src/hooks/useRefValue.ts b/src/hooks/useRefValue.ts new file mode 100644 index 00000000..dcce2c4a --- /dev/null +++ b/src/hooks/useRefValue.ts @@ -0,0 +1,15 @@ +import { useRef } from "react" + +// @see https://react.dev/reference/react/useRef#avoiding-recreating-the-ref-contents +export const useRefValue = (value: () => T): T => { + const ref = useRef() + + const onceRef = useRef(false) + + if (!onceRef.current) { + ref.current = value() + onceRef.current = true + } + + return ref.current! +} diff --git a/src/hooks/useRouterEvents.ts b/src/hooks/useRouterEvents.ts index d455cd93..2f17a0c1 100644 --- a/src/hooks/useRouterEvents.ts +++ b/src/hooks/useRouterEvents.ts @@ -1,19 +1,51 @@ import { usePathname, useRouter, useSearchParams } from "next/navigation" -import { useEffect, useRef, useState } from "react" +import { useEffect, useState } from "react" import { pick } from "~/lib/utils" +import { useRefValue } from "./useRefValue" + interface RouterNavigationEvent {} type RouterEventFunction = (e: RouterNavigationEvent) => void +const createRegister = () => { + const props = { + onStartQ: [] as RouterEventFunction[], + // onErrorQ: [] as RouterEventFunction[], + onCompleteQ: [] as RouterEventFunction[], + } as { + onStartQ: RouterEventFunction[] + // onErrorQ: RouterEventFunction[] + onCompleteQ: RouterEventFunction[] + onStart: (cb: RouterEventFunction) => () => void + // onError: (cb: RouterEventFunction) => () => void + onComplete: (cb: RouterEventFunction) => () => void + } + props.onStart = (cb: RouterEventFunction) => { + props.onStartQ.push(cb) + return () => { + props.onStartQ = props.onStartQ.filter(($) => $ !== cb) + } + } + + props.onComplete = (cb: RouterEventFunction) => { + props.onCompleteQ.push(cb) + return () => { + props.onCompleteQ = props.onCompleteQ.filter(($) => $ !== cb) + } + } + + return props +} + // TODO detect error event export const useAppRouterEventerListener = () => { const [isRouterComplete, setIsRouterComplete] = useState(false) const startChangeCallback = () => { setIsRouterComplete(false) - eventsRegisters.current.onStartQ.forEach(($) => $(buildEvent())) + eventsRegisters.onStartQ.forEach(($) => $(buildEvent())) } const router = useRouter() useEffect(() => { @@ -48,26 +80,7 @@ export const useAppRouterEventerListener = () => { } }, []) - const eventsRegisters = useRef({ - onStartQ: [] as RouterEventFunction[], - // onErrorQ: [] as RouterEventFunction[], - onCompleteQ: [] as RouterEventFunction[], - onStart(cb: RouterEventFunction) { - eventsRegisters.current.onStartQ.push(cb) - return () => { - eventsRegisters.current.onStartQ = - eventsRegisters.current.onStartQ.filter(($) => $ !== cb) - } - }, - - onComplete(cb: RouterEventFunction) { - eventsRegisters.current.onCompleteQ.push(cb) - return () => { - eventsRegisters.current.onCompleteQ = - eventsRegisters.current.onCompleteQ.filter(($) => $ !== cb) - } - }, - }) + const eventsRegisters = useRefValue(createRegister) const buildEvent = (): RouterNavigationEvent => { return { @@ -78,7 +91,7 @@ export const useAppRouterEventerListener = () => { useEffect(() => { if (!isRouterComplete) return - eventsRegisters.current.onCompleteQ.forEach(($) => $(buildEvent())) + eventsRegisters.onCompleteQ.forEach(($) => $(buildEvent())) }, [isRouterComplete]) const currentPathname = usePathname() @@ -94,5 +107,5 @@ export const useAppRouterEventerListener = () => { } }, [currentPathname, searchParams]) - return pick(eventsRegisters.current, ["onStart", "onComplete"]) + return pick(eventsRegisters, ["onStart", "onComplete"]) }