From 4c98b1036ee4b98094359fdc4d198caa09493308 Mon Sep 17 00:00:00 2001 From: Ryan Albrecht Date: Tue, 12 May 2026 14:04:49 -0700 Subject: [PATCH 1/3] ref(explore): Migrate replayQueryParamsProvider from updateNullableLocation to nuqs Replace the deprecated updateNullableLocation pattern with nuqs useQueryStates for managing URL query params in the replay list provider. This removes dependencies on useLocation, useNavigate, and manual Location object mutation. --- .../list/replayQueryParamsProvider.tsx | 76 ++++++------------- 1 file changed, 25 insertions(+), 51 deletions(-) diff --git a/static/app/views/explore/replays/list/replayQueryParamsProvider.tsx b/static/app/views/explore/replays/list/replayQueryParamsProvider.tsx index afbb2087199b93..3e499f786835f1 100644 --- a/static/app/views/explore/replays/list/replayQueryParamsProvider.tsx +++ b/static/app/views/explore/replays/list/replayQueryParamsProvider.tsx @@ -1,74 +1,48 @@ import type {ReactNode} from 'react'; import {useCallback, useMemo} from 'react'; -import type {Location} from 'history'; +import {parseAsString, useQueryStates} from 'nuqs'; -import {updateNullableLocation} from 'sentry/utils/url/updateNullableLocation'; -import {useLocation} from 'sentry/utils/useLocation'; -import {useNavigate} from 'sentry/utils/useNavigate'; import {Mode} from 'sentry/views/explore/contexts/pageParamsContext/mode'; import {QueryParamsContextProvider} from 'sentry/views/explore/queryParams/context'; -import {getQueryFromLocation} from 'sentry/views/explore/queryParams/query'; import {ReadableQueryParams} from 'sentry/views/explore/queryParams/readableQueryParams'; -import { - getIdFromLocation, - getTitleFromLocation, - ID_KEY, - TITLE_KEY, -} from 'sentry/views/explore/queryParams/savedQuery'; import type {WritableQueryParams} from 'sentry/views/explore/queryParams/writableQueryParams'; -const REPLAY_QUERY_KEY = 'query'; - -function getReadableQueryParamsFromLocation(location: Location): ReadableQueryParams { - const query = getQueryFromLocation(location, REPLAY_QUERY_KEY) ?? ''; - const id = getIdFromLocation(location, ID_KEY); - const title = getTitleFromLocation(location, TITLE_KEY); - - return new ReadableQueryParams({ - extrapolate: false, - mode: Mode.SAMPLES, - query, - cursor: '', - fields: [], - sortBys: [], - aggregateCursor: '', - aggregateFields: [], - aggregateSortBys: [], - id, - title, - }); -} - -function getTargetWithReadableQueryParams( - location: Location, - writableQueryParams: WritableQueryParams -): Location { - const target: Location = {...location, query: {...location.query}}; - - updateNullableLocation(target, REPLAY_QUERY_KEY, writableQueryParams.query); - - return target; -} - interface ReplayQueryParamsProviderProps { children: ReactNode; } export function ReplayQueryParamsProvider({children}: ReplayQueryParamsProviderProps) { - const location = useLocation(); - const navigate = useNavigate(); + const [queryParams, setNuqsParams] = useQueryStates({ + query: parseAsString.withDefault(''), + id: parseAsString, + title: parseAsString, + }); const readableQueryParams = useMemo( - () => getReadableQueryParamsFromLocation(location), - [location] + () => + new ReadableQueryParams({ + extrapolate: false, + mode: Mode.SAMPLES, + query: queryParams.query, + cursor: '', + fields: [], + sortBys: [], + aggregateCursor: '', + aggregateFields: [], + aggregateSortBys: [], + id: queryParams.id ?? undefined, + title: queryParams.title ?? undefined, + }), + [queryParams.query, queryParams.id, queryParams.title] ); const setWritableQueryParams = useCallback( (writableQueryParams: WritableQueryParams) => { - const target = getTargetWithReadableQueryParams(location, writableQueryParams); - navigate(target); + setNuqsParams({ + query: writableQueryParams.query ?? null, + }); }, - [location, navigate] + [setNuqsParams] ); return ( From 235ccaeb716d7ef03a15139931fc0d20c30e11f5 Mon Sep 17 00:00:00 2001 From: "getsantry[bot]" <66042841+getsantry[bot]@users.noreply.github.com> Date: Wed, 13 May 2026 17:27:13 +0000 Subject: [PATCH 2/3] :hammer_and_wrench: apply pre-commit fixes --- .../views/explore/replays/list/replayQueryParamsProvider.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/static/app/views/explore/replays/list/replayQueryParamsProvider.tsx b/static/app/views/explore/replays/list/replayQueryParamsProvider.tsx index 04f9b9e16b4626..3e499f786835f1 100644 --- a/static/app/views/explore/replays/list/replayQueryParamsProvider.tsx +++ b/static/app/views/explore/replays/list/replayQueryParamsProvider.tsx @@ -4,9 +4,9 @@ import {parseAsString, useQueryStates} from 'nuqs'; import {Mode} from 'sentry/views/explore/contexts/pageParamsContext/mode'; import {QueryParamsContextProvider} from 'sentry/views/explore/queryParams/context'; -import {ReadableQueryParams} from 'sentry/views/explore/queryParams/readableQueryParams'; +import {ReadableQueryParams} from 'sentry/views/explore/queryParams/readableQueryParams'; import type {WritableQueryParams} from 'sentry/views/explore/queryParams/writableQueryParams'; - + interface ReplayQueryParamsProviderProps { children: ReactNode; } From c801ba60f36d15c6f6844e8a46181c9dc4edce30 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Wed, 13 May 2026 17:42:08 +0000 Subject: [PATCH 3/3] ref(explore): Fix undefined query preservation semantics in nuqs migration Remove the ?? null coercion on query param to preserve the old behavior: - undefined should preserve current query param (no-op) - null should remove it from the URL Both updateNullableLocation and nuqs have the same semantics for undefined vs null, so we don't need to coerce undefined to null. Co-authored-by: Ryan Albrecht --- .../views/explore/replays/list/replayQueryParamsProvider.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/static/app/views/explore/replays/list/replayQueryParamsProvider.tsx b/static/app/views/explore/replays/list/replayQueryParamsProvider.tsx index 3e499f786835f1..efda8d08dc08c6 100644 --- a/static/app/views/explore/replays/list/replayQueryParamsProvider.tsx +++ b/static/app/views/explore/replays/list/replayQueryParamsProvider.tsx @@ -39,7 +39,7 @@ export function ReplayQueryParamsProvider({children}: ReplayQueryParamsProviderP const setWritableQueryParams = useCallback( (writableQueryParams: WritableQueryParams) => { setNuqsParams({ - query: writableQueryParams.query ?? null, + query: writableQueryParams.query, }); }, [setNuqsParams]