mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-05-23 11:57:50 -05:00
45 lines
1.3 KiB
TypeScript
45 lines
1.3 KiB
TypeScript
import { useSearchParams } from "@remix-run/react";
|
|
import * as React from "react";
|
|
|
|
/** State backed search params. Used when you want to update search params without triggering navigation (runs loaders, rerenders the whole page extra time) */
|
|
export function useSearchParamState<T>({
|
|
defaultValue,
|
|
name,
|
|
revive,
|
|
}: {
|
|
defaultValue: T;
|
|
name: string;
|
|
/** Function to revive string from search params to value. If returns a null or undefined value then defaultValue gets used. */
|
|
revive: (value: string) => T | null | undefined;
|
|
}) {
|
|
const [initialSearchParams] = useSearchParams();
|
|
const [state, setState] = React.useState<T>(resolveInitialState());
|
|
|
|
const handleChange = React.useCallback(
|
|
(newValue: T) => {
|
|
setState(newValue);
|
|
|
|
const searchParams = new URLSearchParams(window.location.search);
|
|
searchParams.set(name, String(newValue));
|
|
|
|
window.history.replaceState(
|
|
{},
|
|
"",
|
|
`${window.location.pathname}?${String(searchParams)}`,
|
|
);
|
|
},
|
|
[name],
|
|
);
|
|
|
|
return [state, handleChange] as const;
|
|
|
|
function resolveInitialState() {
|
|
const value = initialSearchParams.get(name);
|
|
if (value === null || value === undefined) {
|
|
return defaultValue;
|
|
}
|
|
|
|
return revive(value) ?? defaultValue;
|
|
}
|
|
}
|