Skip to content

Instantly share code, notes, and snippets.

@klarstrup
Created September 23, 2019 22:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save klarstrup/f5f0126badfbd9893ae1d68ad73aaa1b to your computer and use it in GitHub Desktop.
Save klarstrup/f5f0126badfbd9893ae1d68ad73aaa1b to your computer and use it in GitHub Desktop.
import qs from "qs";
import { useEffect, useMemo, useState } from "react";
import { useRouter } from "../routing";
const identity = a => a;
const defined = a => typeof a !== "undefined";
const fromQueryString = query => qs.parse(query, { ignoreQueryPrefix: true });
const toQueryString = object => qs.stringify(object, { addQueryPrefix: true });
export default function useQueryParam(
paramName,
defaultValue,
{ validator = defined, serializer = identity, deserializer = identity } = {},
) {
const {
location: { search },
history,
} = useRouter();
const queryParameters = useMemo(() => fromQueryString(search), [search]);
const queryParameterValue = deserializer(queryParameters[paramName]);
const [value, setValue] = useState(
validator(queryParameterValue) ? queryParameterValue : defaultValue,
);
const sValue = useMemo(() => serializer(value), [serializer, value]);
const nextSearch = useMemo(
() =>
toQueryString({
...queryParameters,
[paramName]: sValue === serializer(defaultValue) ? undefined : sValue,
}),
[defaultValue, paramName, queryParameters, sValue, serializer],
);
useEffect(() => {
if (nextSearch !== search) history.replace({ search: nextSearch });
}, [history, nextSearch, search]);
return [value, setValue];
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment