Skip to content

Instantly share code, notes, and snippets.

@dclstn
Last active December 11, 2024 15:59
Show Gist options
  • Select an option

  • Save dclstn/45d0421ad72dc21667d2a15c9cbb3743 to your computer and use it in GitHub Desktop.

Select an option

Save dclstn/45d0421ad72dc21667d2a15c9cbb3743 to your computer and use it in GitHub Desktop.
A useful hook for managing query state
import React from 'react';
interface useQueryStateConfig<T> {
parse?: (value: string) => T;
serialize?: (value: T) => string;
defaultValue: T;
}
export default function useQueryState<T>(
key: string,
config: useQueryStateConfig<T>
): readonly [T, (value: T | null) => void] {
const [value, setValue] = React.useState<T>(() => {
const query = new URLSearchParams(window.location.search).get(key);
if (query == null) {
return config.defaultValue;
}
if (config.parse == null) {
return query as T;
}
return config.parse(query);
});
const setQuery = React.useCallback(
(value: T | null): void => {
setValue(value as T);
const newParams = new URLSearchParams(window.location.search);
if (value != null && config.serialize != null) {
value = config.serialize(value) as T;
}
if (value === config.defaultValue) {
newParams.delete(key);
} else {
newParams.set(key, value as unknown as string);
}
if (newParams.toString().length === 0) {
window.history.replaceState(null, '', window.location.pathname);
return;
}
window.history.replaceState(null, '', `${window.location.pathname}?${newParams}`);
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[key, config.serialize, config.defaultValue]
);
return [value, setQuery] as const;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment