From e0240c59d64c1aec9e1c6a0b772f23ffa3da76d4 Mon Sep 17 00:00:00 2001 From: matlin Date: Thu, 2 Oct 2025 19:10:06 -0500 Subject: [PATCH] fix: upgrade nuqs to properly support url param arrays for sorts and filters (#39214) * upgrade nuqs to get proper native url array params * use next useSearchParams because nuqs is stale --- .../components/grid/SupabaseGrid.utils.ts | 23 +++++++++++++------ apps/studio/package.json | 2 +- pnpm-lock.yaml | 16 ++++++++----- 3 files changed, 27 insertions(+), 14 deletions(-) diff --git a/apps/studio/components/grid/SupabaseGrid.utils.ts b/apps/studio/components/grid/SupabaseGrid.utils.ts index ec803d13c2959..b8997e3504e7d 100644 --- a/apps/studio/components/grid/SupabaseGrid.utils.ts +++ b/apps/studio/components/grid/SupabaseGrid.utils.ts @@ -1,17 +1,17 @@ import AwesomeDebouncePromise from 'awesome-debounce-promise' -import { compact, filter } from 'lodash' -import { useEffect, useState } from 'react' +import { compact } from 'lodash' +import { useEffect, useMemo } from 'react' import { CalculatedColumn, CellKeyboardEvent } from 'react-data-grid' import type { Filter, SavedState } from 'components/grid/types' import { Entity, isTableLike } from 'data/table-editor/table-editor-types' -import { useUrlState } from 'hooks/ui/useUrlState' import { copyToClipboard } from 'ui' import { FilterOperatorOptions } from './components/header/filter/Filter.constants' import { STORAGE_KEY_PREFIX } from './constants' import type { Sort, SupaColumn, SupaTable } from './types' import { formatClipboardValue } from './utils/common' -import { parseAsArrayOf, parseAsBoolean, parseAsString, useQueryStates } from 'nuqs' +import { parseAsNativeArrayOf, parseAsBoolean, parseAsString, useQueryStates } from 'nuqs' +import { useSearchParams } from 'next/navigation' export const LOAD_TAB_FROM_CACHE_PARAM = 'loadFromCache' @@ -197,16 +197,25 @@ export function useSyncTableEditorStateFromLocalStorageWithUrl({ projectRef: string | undefined table: Entity | undefined }) { - const [urlParams, updateUrlParams] = useQueryStates( + // Warning: nuxt url state often fails to update to changes to URL + const [, updateUrlParams] = useQueryStates( { - sort: parseAsArrayOf(parseAsString).withDefault([]), - filter: parseAsArrayOf(parseAsString).withDefault([]), + sort: parseAsNativeArrayOf(parseAsString), + filter: parseAsNativeArrayOf(parseAsString), [LOAD_TAB_FROM_CACHE_PARAM]: parseAsBoolean.withDefault(false), }, { history: 'replace', } ) + // Use nextjs useSearchParams to get the latest URL params + const searchParams = useSearchParams() + const urlParams = useMemo(() => { + const sort = searchParams.getAll('sort') + const filter = searchParams.getAll('filter') + const loadFromCache = !!searchParams.get(LOAD_TAB_FROM_CACHE_PARAM) + return { sort, filter, loadFromCache } + }, [searchParams]) useEffect(() => { if (!projectRef || !table) { diff --git a/apps/studio/package.json b/apps/studio/package.json index f84058e366c9a..e953bdf30b3ef 100644 --- a/apps/studio/package.json +++ b/apps/studio/package.json @@ -99,7 +99,7 @@ "monaco-editor": "0.52.2", "next": "catalog:", "next-themes": "^0.3.0", - "nuqs": "^2.4.1", + "nuqs": "2.7.0", "openai": "^4.75.1", "openapi-fetch": "0.12.4", "papaparse": "^5.3.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 41bbae33039ce..23f69a3750df9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -937,8 +937,8 @@ importers: specifier: ^0.3.0 version: 0.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) nuqs: - specifier: ^2.4.1 - version: 2.4.1(next@15.5.2(@babel/core@7.28.4(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(react-router@7.5.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1) + specifier: 2.7.0 + version: 2.7.0(@tanstack/react-router@1.114.27(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(next@15.5.2(@babel/core@7.28.4(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(react-router@7.5.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1) openai: specifier: ^4.75.1 version: 4.104.0(encoding@0.1.13)(ws@8.18.3)(zod@3.25.76) @@ -15609,10 +15609,11 @@ packages: peerDependencies: next: '>=13.4 <14.0.2 || ^14.0.3' - nuqs@2.4.1: - resolution: {integrity: sha512-u6sngTspqDe3jWHtcmqHQg3dl35niizCZAsm5gy7PBlgG2rwl71Dp2QUv5hwBaWKI9qz0wqILZY86TsRxq66SQ==} + nuqs@2.7.0: + resolution: {integrity: sha512-p6j6AuOVbnIlMSOlymKVDQtDkSCgjKxikwrqE9zThEOrP0UMfB/dwHuc6nKCuBPveoNghbh15zwoyTTv0XLp+A==} peerDependencies: '@remix-run/react': '>=2' + '@tanstack/react-router': ^1 next: '>=14.2.0' react: '>=18.2.0 || ^19.0.0-0' react-router: ^6 || ^7 @@ -15620,6 +15621,8 @@ packages: peerDependenciesMeta: '@remix-run/react': optional: true + '@tanstack/react-router': + optional: true next: optional: true react-router: @@ -37451,11 +37454,12 @@ snapshots: mitt: 3.0.1 next: 15.5.2(@babel/core@7.28.4(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4) - nuqs@2.4.1(next@15.5.2(@babel/core@7.28.4(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(react-router@7.5.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1): + nuqs@2.7.0(@tanstack/react-router@1.114.27(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(next@15.5.2(@babel/core@7.28.4(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(react-router@7.5.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1): dependencies: - mitt: 3.0.1 + '@standard-schema/spec': 1.0.0 react: 18.3.1 optionalDependencies: + '@tanstack/react-router': 1.114.27(react-dom@18.3.1(react@18.3.1))(react@18.3.1) next: 15.5.2(@babel/core@7.28.4(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4) react-router: 7.5.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1)