`parser.defaultValue` is `undefined` instead of `null`
Context
What's your version of nuqs?
"nuqs": "2.8.3"
What framework are you using?
- ❌ Next.js (app router)
- ❌ Next.js (pages router)
- ❌ React SPA (no router)
- ❌ Remix
- ✅ React Router
- ❌ Other (please specify)
Which version of your framework are you using?
"react-router": "7.10.1",
"react": "19.2.1",
Description
I am trying to implement the function mentioned in https://github.com/47ng/nuqs/discussions/860 which mostly works for detecting when the default value of URL keys have changed. But I am hitting an edge case where the keys without defaults are set as undefined so as a result the function always returns false.
Reproduction
Here is a minimal reproduction:
import {
type inferParserType,
parseAsString,
parseAsStringEnum,
type ParserMap,
useQueryStates,
} from "nuqs";
enum Animal {
Dog = "Dog",
Cat = "Cat",
Bird = "Bird",
}
enum Color {
Red = "Red",
Green = "Green",
Blue = "Blue",
}
enum Size {
Small = "Small",
Medium = "Medium",
Large = "Large",
}
const defaultQueryState = {
query: parseAsString.withDefault(""),
color: parseAsStringEnum(Object.values(Color)),
animal: parseAsStringEnum(Object.values(Animal)),
size: parseAsStringEnum(Object.values(Size)).withDefault(Size.Medium),
};
function isDefaultState<Parsers extends ParserMap>(
parsers: Parsers,
values: inferParserType<Parsers>,
): boolean {
for (const [key, parser] of Object.entries(parsers)) {
console.log({
key,
value: values[key],
defaultValue: parsers[key].defaultValue,
});
if (!parser.eq(values[key], parsers[key].defaultValue)) {
return false;
}
}
return true;
}
export default function Page() {
const [filters] = useQueryStates(defaultQueryState);
const isDefault = isDefaultState(defaultQueryState, filters);
return (
<div>
<p>Testing Page</p>
<p>Current Filters: {JSON.stringify(filters)}</p>
<p>Is Default State: {JSON.stringify({ isDefault })}</p>
</div>
);
}
Browser view:
Console view:
(the function is returning early since the check fails in the second loop, thus the other keys are not logged)
Expected behavior
I expect the function to return true.
That's not a bug, null is the value that's returned when there is no default value specified (ie: when it's undefined), so you'd have to take it into account in your function:
function isDefaultState<Parsers extends ParserMap>(
parsers: Parsers,
values: inferParserType<Parsers>,
): boolean {
for (const [key, parser] of Object.entries(parsers)) {
console.log({
key,
value: values[key],
defaultValue: parsers[key].defaultValue,
});
+ if (parsers[key].defaultValue === undefined && values[key] !== null) {
+ return false
+ }
if (!parser.eq(values[key], parsers[key].defaultValue)) {
return false;
}
}
return true;
}
Is null is the default value then shouldn’t parser.defaultValue also return null?