From 58dcd9eae5340153aaa15d3fe91c3d7fc0b5735a Mon Sep 17 00:00:00 2001 From: Hugo Tiger <49451774+hugotiger@users.noreply.github.com> Date: Thu, 19 Sep 2024 10:04:44 +0200 Subject: [PATCH 1/2] fix: Handle `clearOnDefault` in `createSerializer` --- packages/nuqs/src/serializer.test.ts | 31 +++++++++++++++++++++++++++- packages/nuqs/src/serializer.ts | 8 ++++++- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/packages/nuqs/src/serializer.test.ts b/packages/nuqs/src/serializer.test.ts index f90ad52e..d854f82a 100644 --- a/packages/nuqs/src/serializer.test.ts +++ b/packages/nuqs/src/serializer.test.ts @@ -1,5 +1,11 @@ import { describe, expect, test } from 'vitest' -import { parseAsBoolean, parseAsInteger, parseAsString } from './parsers' +import { + parseAsBoolean, + parseAsInteger, + parseAsString, + parseAsJson, + parseAsArrayOf +} from './parsers' import { createSerializer } from './serializer' const parsers = { @@ -62,4 +68,27 @@ describe('serializer', () => { const result = serialize('?str=bar&int=-1', { str: 'foo', int: null }) expect(result).toBe('?str=foo') }) + test('clears value when setting the default value when `clearOnDefault` is used', () => { + const serialize = createSerializer({ + int: parseAsInteger.withOptions({ clearOnDefault: true }).withDefault(0), + str: parseAsString.withOptions({ clearOnDefault: true }).withDefault(''), + bool: parseAsBoolean + .withOptions({ clearOnDefault: true }) + .withDefault(false), + arr: parseAsArrayOf(parseAsString) + .withOptions({ clearOnDefault: true }) + .withDefault([]), + json: parseAsJson() + .withOptions({ clearOnDefault: true }) + .withDefault({ foo: 'bar' }) + }) + const result = serialize({ + int: 0, + str: '', + bool: false, + arr: [], + json: { foo: 'bar' } + }) + expect(result).toBe('') + }) }) diff --git a/packages/nuqs/src/serializer.ts b/packages/nuqs/src/serializer.ts index f2caf14c..ceac696d 100644 --- a/packages/nuqs/src/serializer.ts +++ b/packages/nuqs/src/serializer.ts @@ -41,7 +41,13 @@ export function createSerializer< if (!parser || value === undefined) { continue } - if (value === null) { + const isMatchingDefault = + // @ts-expect-error + parser.defaultValue !== undefined && + // @ts-expect-error + (parser.eq ?? ((a, b) => a === b))(value, parser.defaultValue) + + if (value === null || (parser.clearOnDefault && isMatchingDefault)) { search.delete(key) } else { search.set(key, parser.serialize(value)) From 0d1351f857734a9c2f01083abd12168c27fb7912 Mon Sep 17 00:00:00 2001 From: Francois Best Date: Thu, 19 Sep 2024 11:20:05 +0200 Subject: [PATCH 2/2] chore: Fix types --- packages/nuqs/src/serializer.test.ts | 4 ++-- packages/nuqs/src/serializer.ts | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/packages/nuqs/src/serializer.test.ts b/packages/nuqs/src/serializer.test.ts index d854f82a..1115fd15 100644 --- a/packages/nuqs/src/serializer.test.ts +++ b/packages/nuqs/src/serializer.test.ts @@ -1,10 +1,10 @@ import { describe, expect, test } from 'vitest' import { + parseAsArrayOf, parseAsBoolean, parseAsInteger, - parseAsString, parseAsJson, - parseAsArrayOf + parseAsString } from './parsers' import { createSerializer } from './serializer' diff --git a/packages/nuqs/src/serializer.ts b/packages/nuqs/src/serializer.ts index ceac696d..8da2e65c 100644 --- a/packages/nuqs/src/serializer.ts +++ b/packages/nuqs/src/serializer.ts @@ -10,9 +10,10 @@ type Base = string | URLSearchParams | URL type Values>> = Partial<{ [K in keyof Parsers]?: ExtractParserType }> +type ParserWithOptionalDefault = ParserBuilder & { defaultValue?: T } export function createSerializer< - Parsers extends Record> + Parsers extends Record> >(parsers: Parsers) { /** * Generate a query string for the given values. @@ -42,9 +43,7 @@ export function createSerializer< continue } const isMatchingDefault = - // @ts-expect-error parser.defaultValue !== undefined && - // @ts-expect-error (parser.eq ?? ((a, b) => a === b))(value, parser.defaultValue) if (value === null || (parser.clearOnDefault && isMatchingDefault)) {