nuqs-zod-adapter
Version:
A Nuqs adapter to safely bind Zod schemas with query parameters using type safety, debouncing and auto-reset support.
62 lines (61 loc) • 2.08 kB
JavaScript
import { useQueryState, parseAsString, parseAsInteger, parseAsBoolean } from 'nuqs';
import { useDebouncedCallback } from 'use-debounce';
import { useEffect, useState } from 'react';
export function useSafeQueryStateFromZod(key, schema, options) {
let baseSchema = schema;
let defaultValue = undefined;
if (schema._def.typeName === 'ZodDefault') {
defaultValue = schema._def.defaultValue();
baseSchema = schema._def.innerType;
}
const typeName = baseSchema._def.typeName;
let parser;
switch (typeName) {
case 'ZodString':
case 'ZodEnum':
case 'ZodNativeEnum':
case 'ZodLiteral':
case 'ZodUnion':
parser = parseAsString.withDefault(defaultValue);
break;
case 'ZodNumber':
parser = parseAsInteger.withDefault(defaultValue);
break;
case 'ZodBoolean':
parser = parseAsBoolean.withDefault(defaultValue);
break;
case 'ZodEffects':
if (baseSchema._def.schema?._def?.typeName === 'ZodNumber') {
parser = parseAsInteger.withDefault(defaultValue);
}
else {
parser = parseAsString.withDefault(defaultValue);
}
break;
default:
}
const [rawValue, setRaw] = useQueryState(key, {
...parser,
...options
});
const delay = options?.delay;
const resetKeys = options?.resetKeys ?? [];
if (!delay)
return [rawValue ?? defaultValue, setRaw];
const [internalValue, setInternalValue] = useState(rawValue);
const debouncedSet = useDebouncedCallback((v) => {
setRaw(v);
for (const rk of resetKeys) {
const [, resetSetter] = useQueryState(rk, parseAsString.withDefault(''));
resetSetter(null);
}
}, delay);
const set = (v) => {
setInternalValue(v);
debouncedSet(v);
};
useEffect(() => {
setInternalValue(rawValue);
}, [rawValue]);
return [internalValue ?? defaultValue, set];
}