Skip to content

Commit a1aa096

Browse files
hugotigerfranky47
andauthored
fix: Serialization of default values in createSerializer (#642)
* fix: Handle `clearOnDefault` in `createSerializer` * chore: Fix types --------- Co-authored-by: Francois Best <github@francoisbest.com>
1 parent 9dc148f commit a1aa096

File tree

2 files changed

+37
-3
lines changed

2 files changed

+37
-3
lines changed

packages/nuqs/src/serializer.test.ts

+30-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
import { describe, expect, test } from 'vitest'
2-
import { parseAsBoolean, parseAsInteger, parseAsString } from './parsers'
2+
import {
3+
parseAsArrayOf,
4+
parseAsBoolean,
5+
parseAsInteger,
6+
parseAsJson,
7+
parseAsString
8+
} from './parsers'
39
import { createSerializer } from './serializer'
410

511
const parsers = {
@@ -62,4 +68,27 @@ describe('serializer', () => {
6268
const result = serialize('?str=bar&int=-1', { str: 'foo', int: null })
6369
expect(result).toBe('?str=foo')
6470
})
71+
test('clears value when setting the default value when `clearOnDefault` is used', () => {
72+
const serialize = createSerializer({
73+
int: parseAsInteger.withOptions({ clearOnDefault: true }).withDefault(0),
74+
str: parseAsString.withOptions({ clearOnDefault: true }).withDefault(''),
75+
bool: parseAsBoolean
76+
.withOptions({ clearOnDefault: true })
77+
.withDefault(false),
78+
arr: parseAsArrayOf(parseAsString)
79+
.withOptions({ clearOnDefault: true })
80+
.withDefault([]),
81+
json: parseAsJson()
82+
.withOptions({ clearOnDefault: true })
83+
.withDefault({ foo: 'bar' })
84+
})
85+
const result = serialize({
86+
int: 0,
87+
str: '',
88+
bool: false,
89+
arr: [],
90+
json: { foo: 'bar' }
91+
})
92+
expect(result).toBe('')
93+
})
6594
})

packages/nuqs/src/serializer.ts

+7-2
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@ type Base = string | URLSearchParams | URL
1010
type Values<Parsers extends Record<string, ParserBuilder<any>>> = Partial<{
1111
[K in keyof Parsers]?: ExtractParserType<Parsers[K]>
1212
}>
13+
type ParserWithOptionalDefault<T> = ParserBuilder<T> & { defaultValue?: T }
1314

1415
export function createSerializer<
15-
Parsers extends Record<string, ParserBuilder<any>>
16+
Parsers extends Record<string, ParserWithOptionalDefault<any>>
1617
>(parsers: Parsers) {
1718
/**
1819
* Generate a query string for the given values.
@@ -41,7 +42,11 @@ export function createSerializer<
4142
if (!parser || value === undefined) {
4243
continue
4344
}
44-
if (value === null) {
45+
const isMatchingDefault =
46+
parser.defaultValue !== undefined &&
47+
(parser.eq ?? ((a, b) => a === b))(value, parser.defaultValue)
48+
49+
if (value === null || (parser.clearOnDefault && isMatchingDefault)) {
4550
search.delete(key)
4651
} else {
4752
search.set(key, parser.serialize(value))

0 commit comments

Comments
 (0)