From 91017dd422a212ff3284f3219f58500e1954667f Mon Sep 17 00:00:00 2001 From: jerryzhou196 Date: Wed, 12 Nov 2025 13:48:56 -0500 Subject: [PATCH 1/4] refactor(replays): Rename and export default sort constant for replay list; update usages across components - Changed `DEFAULT_SORT` to `DEFAULT_REPLAY_LIST_SORT` for clarity and consistency. - Updated `useReplayTableSort` to use the new constant. - Removed unused `DEFAULT_SORT` from `fetchReplayList`. - Updated sorting logic in `useReplaysFromIssue` and `useReplaysFromTransaction` to utilize the new constant. - Marked `useReplayList` as deprecated in favor of `useApiQuery`. --- static/app/components/replays/table/useReplayTableSort.tsx | 4 ++-- static/app/utils/replays/fetchReplayList.tsx | 2 -- static/app/utils/replays/hooks/useReplayList.tsx | 3 +++ .../views/issueDetails/groupReplays/useReplaysFromIssue.tsx | 6 +++--- .../transactionReplays/useReplaysFromTransaction.tsx | 6 +++--- 5 files changed, 11 insertions(+), 10 deletions(-) diff --git a/static/app/components/replays/table/useReplayTableSort.tsx b/static/app/components/replays/table/useReplayTableSort.tsx index 438e2101797d2b..2bbb31c97afd25 100644 --- a/static/app/components/replays/table/useReplayTableSort.tsx +++ b/static/app/components/replays/table/useReplayTableSort.tsx @@ -12,10 +12,10 @@ interface Props { queryParamKey?: string; } -const DEFAULT_SORT = {field: 'started_at', kind: 'desc'} as const; +export const DEFAULT_REPLAY_LIST_SORT = {field: 'started_at', kind: 'desc'} as const; export default function useReplayTableSort({ - defaultSort = DEFAULT_SORT, + defaultSort = DEFAULT_REPLAY_LIST_SORT, queryParamKey = 'sort', }: Props = {}) { const organization = useOrganization(); diff --git a/static/app/utils/replays/fetchReplayList.tsx b/static/app/utils/replays/fetchReplayList.tsx index 1adde8fc346219..904e087352fc52 100644 --- a/static/app/utils/replays/fetchReplayList.tsx +++ b/static/app/utils/replays/fetchReplayList.tsx @@ -10,8 +10,6 @@ import {mapResponseToReplayRecord} from 'sentry/utils/replays/replayDataUtils'; import type RequestError from 'sentry/utils/requestError/requestError'; import type {ReplayListQueryReferrer, ReplayListRecord} from 'sentry/views/replays/types'; -export const DEFAULT_SORT = '-started_at'; - type State = { fetchError: undefined | RequestError; pageLinks: null | string; diff --git a/static/app/utils/replays/hooks/useReplayList.tsx b/static/app/utils/replays/hooks/useReplayList.tsx index cc58a33c6392ae..1014105e6d712e 100644 --- a/static/app/utils/replays/hooks/useReplayList.tsx +++ b/static/app/utils/replays/hooks/useReplayList.tsx @@ -24,6 +24,9 @@ type State = Awaited> & {isFetching: boolean} type Result = State; +/** + * @deprecated use useApiQuery instead + */ function useReplayList({ enabled = true, eventView, diff --git a/static/app/views/issueDetails/groupReplays/useReplaysFromIssue.tsx b/static/app/views/issueDetails/groupReplays/useReplaysFromIssue.tsx index d6685445d94bff..4cc7a369a03ce6 100644 --- a/static/app/views/issueDetails/groupReplays/useReplaysFromIssue.tsx +++ b/static/app/views/issueDetails/groupReplays/useReplaysFromIssue.tsx @@ -2,12 +2,12 @@ import {useCallback, useEffect, useMemo, useState} from 'react'; import * as Sentry from '@sentry/react'; import type {Location} from 'history'; +import {DEFAULT_REPLAY_LIST_SORT} from 'sentry/components/replays/table/useReplayTableSort'; import {ALL_ACCESS_PROJECTS} from 'sentry/constants/pageFilters'; import {IssueCategory, type Group} from 'sentry/types/group'; import type {Organization} from 'sentry/types/organization'; -import EventView from 'sentry/utils/discover/eventView'; +import EventView, {encodeSort} from 'sentry/utils/discover/eventView'; import {decodeScalar} from 'sentry/utils/queryString'; -import {DEFAULT_SORT} from 'sentry/utils/replays/fetchReplayList'; import type RequestError from 'sentry/utils/requestError/requestError'; import useApi from 'sentry/utils/useApi'; import useCleanQueryParamsOnRouteLeave from 'sentry/utils/useCleanQueryParamsOnRouteLeave'; @@ -66,7 +66,7 @@ export default function useReplaysFromIssue({ query: replayIds.length ? `id:[${String(replayIds)}]` : `id:1`, range: '90d', projects: [], - orderby: decodeScalar(location.query.sort, DEFAULT_SORT), + orderby: decodeScalar(location.query.sort, encodeSort(DEFAULT_REPLAY_LIST_SORT)), }); }, [location.query.sort, replayIds]); diff --git a/static/app/views/performance/transactionSummary/transactionReplays/useReplaysFromTransaction.tsx b/static/app/views/performance/transactionSummary/transactionReplays/useReplaysFromTransaction.tsx index 2afb57413723a4..778acde8dfe94b 100644 --- a/static/app/views/performance/transactionSummary/transactionReplays/useReplaysFromTransaction.tsx +++ b/static/app/views/performance/transactionSummary/transactionReplays/useReplaysFromTransaction.tsx @@ -2,11 +2,11 @@ import {useCallback, useEffect, useMemo, useState} from 'react'; import * as Sentry from '@sentry/react'; import type {Location} from 'history'; +import {DEFAULT_REPLAY_LIST_SORT} from 'sentry/components/replays/table/useReplayTableSort'; import type {Organization} from 'sentry/types/organization'; -import EventView from 'sentry/utils/discover/eventView'; +import EventView, {encodeSort} from 'sentry/utils/discover/eventView'; import {doDiscoverQuery} from 'sentry/utils/discover/genericDiscoverQuery'; import {decodeScalar} from 'sentry/utils/queryString'; -import {DEFAULT_SORT} from 'sentry/utils/replays/fetchReplayList'; import useApi from 'sentry/utils/useApi'; import type {ReplayListLocationQuery} from 'sentry/views/replays/types'; import {REPLAY_LIST_FIELDS} from 'sentry/views/replays/types'; @@ -90,7 +90,7 @@ function useReplaysFromTransaction({ fields: REPLAY_LIST_FIELDS, projects: [], query: response.replayIds.length ? `id:[${String(response.replayIds)}]` : undefined, - orderby: decodeScalar(location.query.sort, DEFAULT_SORT), + orderby: decodeScalar(location.query.sort, encodeSort(DEFAULT_REPLAY_LIST_SORT)), }); }, [location.query.sort, response.replayIds]); From ada7f95184e598520e22b2150d57284aeaf2b274 Mon Sep 17 00:00:00 2001 From: jerryzhou196 Date: Wed, 12 Nov 2025 14:52:40 -0500 Subject: [PATCH 2/4] refactor(replays): Update default sort handling and deprecate related functionality - Changed default sort in `useReplayTableSort` to use a decoded format for consistency. - Updated `orderby` logic in `useReplaysFromIssue` and `useReplaysFromTransaction` to remove unnecessary encoding. - Enhanced deprecation notice in `useReplayList` to clarify its reliance on deprecated components. --- static/app/components/replays/table/useReplayTableSort.tsx | 7 ++++--- static/app/utils/replays/hooks/useReplayList.tsx | 3 ++- .../issueDetails/groupReplays/useReplaysFromIssue.tsx | 4 ++-- .../transactionReplays/useReplaysFromTransaction.tsx | 4 ++-- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/static/app/components/replays/table/useReplayTableSort.tsx b/static/app/components/replays/table/useReplayTableSort.tsx index 2bbb31c97afd25..0c447bda108a98 100644 --- a/static/app/components/replays/table/useReplayTableSort.tsx +++ b/static/app/components/replays/table/useReplayTableSort.tsx @@ -12,10 +12,11 @@ interface Props { queryParamKey?: string; } -export const DEFAULT_REPLAY_LIST_SORT = {field: 'started_at', kind: 'desc'} as const; +export const DEFAULT_REPLAY_LIST_SORT = '-started_at'; +const DEFAULT_DECODED_REPLAY_SORT = decodeSorts(DEFAULT_REPLAY_LIST_SORT).at(0); export default function useReplayTableSort({ - defaultSort = DEFAULT_REPLAY_LIST_SORT, + defaultSort = DEFAULT_DECODED_REPLAY_SORT, queryParamKey = 'sort', }: Props = {}) { const organization = useOrganization(); @@ -29,7 +30,7 @@ export default function useReplayTableSort({ const newSort = { field: key, kind: - key === sortType.field ? (sortType.kind === 'asc' ? 'desc' : 'asc') : 'desc', + key === sortType?.field ? (sortType?.kind === 'asc' ? 'desc' : 'asc') : 'desc', } satisfies Sort; setParamValue(encodeSort(newSort)); diff --git a/static/app/utils/replays/hooks/useReplayList.tsx b/static/app/utils/replays/hooks/useReplayList.tsx index 1014105e6d712e..97c23c33a05336 100644 --- a/static/app/utils/replays/hooks/useReplayList.tsx +++ b/static/app/utils/replays/hooks/useReplayList.tsx @@ -25,7 +25,8 @@ type State = Awaited> & {isFetching: boolean} type Result = State; /** - * @deprecated use useApiQuery instead + * @deprecated due to its reliance on EventView which is also deprecated + * Use useApiQuery instead */ function useReplayList({ enabled = true, diff --git a/static/app/views/issueDetails/groupReplays/useReplaysFromIssue.tsx b/static/app/views/issueDetails/groupReplays/useReplaysFromIssue.tsx index 4cc7a369a03ce6..9f11f509d3ba9f 100644 --- a/static/app/views/issueDetails/groupReplays/useReplaysFromIssue.tsx +++ b/static/app/views/issueDetails/groupReplays/useReplaysFromIssue.tsx @@ -6,7 +6,7 @@ import {DEFAULT_REPLAY_LIST_SORT} from 'sentry/components/replays/table/useRepla import {ALL_ACCESS_PROJECTS} from 'sentry/constants/pageFilters'; import {IssueCategory, type Group} from 'sentry/types/group'; import type {Organization} from 'sentry/types/organization'; -import EventView, {encodeSort} from 'sentry/utils/discover/eventView'; +import EventView from 'sentry/utils/discover/eventView'; import {decodeScalar} from 'sentry/utils/queryString'; import type RequestError from 'sentry/utils/requestError/requestError'; import useApi from 'sentry/utils/useApi'; @@ -66,7 +66,7 @@ export default function useReplaysFromIssue({ query: replayIds.length ? `id:[${String(replayIds)}]` : `id:1`, range: '90d', projects: [], - orderby: decodeScalar(location.query.sort, encodeSort(DEFAULT_REPLAY_LIST_SORT)), + orderby: decodeScalar(location.query.sort, DEFAULT_REPLAY_LIST_SORT), }); }, [location.query.sort, replayIds]); diff --git a/static/app/views/performance/transactionSummary/transactionReplays/useReplaysFromTransaction.tsx b/static/app/views/performance/transactionSummary/transactionReplays/useReplaysFromTransaction.tsx index 778acde8dfe94b..0e21d5e6a40a0b 100644 --- a/static/app/views/performance/transactionSummary/transactionReplays/useReplaysFromTransaction.tsx +++ b/static/app/views/performance/transactionSummary/transactionReplays/useReplaysFromTransaction.tsx @@ -4,7 +4,7 @@ import type {Location} from 'history'; import {DEFAULT_REPLAY_LIST_SORT} from 'sentry/components/replays/table/useReplayTableSort'; import type {Organization} from 'sentry/types/organization'; -import EventView, {encodeSort} from 'sentry/utils/discover/eventView'; +import EventView from 'sentry/utils/discover/eventView'; import {doDiscoverQuery} from 'sentry/utils/discover/genericDiscoverQuery'; import {decodeScalar} from 'sentry/utils/queryString'; import useApi from 'sentry/utils/useApi'; @@ -90,7 +90,7 @@ function useReplaysFromTransaction({ fields: REPLAY_LIST_FIELDS, projects: [], query: response.replayIds.length ? `id:[${String(response.replayIds)}]` : undefined, - orderby: decodeScalar(location.query.sort, encodeSort(DEFAULT_REPLAY_LIST_SORT)), + orderby: decodeScalar(location.query.sort, DEFAULT_REPLAY_LIST_SORT), }); }, [location.query.sort, response.replayIds]); From 0419838ab24fa93b675a265f743b35909fd17310 Mon Sep 17 00:00:00 2001 From: jerryzhou196 Date: Wed, 12 Nov 2025 14:53:44 -0500 Subject: [PATCH 3/4] update message --- static/app/utils/replays/hooks/useReplayList.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/static/app/utils/replays/hooks/useReplayList.tsx b/static/app/utils/replays/hooks/useReplayList.tsx index 97c23c33a05336..6a4affd282f2ea 100644 --- a/static/app/utils/replays/hooks/useReplayList.tsx +++ b/static/app/utils/replays/hooks/useReplayList.tsx @@ -25,7 +25,7 @@ type State = Awaited> & {isFetching: boolean} type Result = State; /** - * @deprecated due to its reliance on EventView which is also deprecated + * @deprecated due to its reliance on EventView which is considered bad practice * Use useApiQuery instead */ function useReplayList({ From 72dcc99576c4b0e639f9f37d9e015869af68d9a6 Mon Sep 17 00:00:00 2001 From: jerryzhou196 Date: Wed, 12 Nov 2025 15:28:32 -0500 Subject: [PATCH 4/4] refactor(replays): Update default sort handling and improve deprecation notice - Changed default sort in `useReplayTableSort` to use a structured format for clarity and consistency. - Updated the deprecation message in `useReplayList` to better reflect the challenges of using `EventView`. --- .../app/components/replays/table/useReplayTableSort.tsx | 8 ++++---- static/app/utils/replays/hooks/useReplayList.tsx | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/static/app/components/replays/table/useReplayTableSort.tsx b/static/app/components/replays/table/useReplayTableSort.tsx index 0c447bda108a98..511f20f9e9c988 100644 --- a/static/app/components/replays/table/useReplayTableSort.tsx +++ b/static/app/components/replays/table/useReplayTableSort.tsx @@ -12,11 +12,11 @@ interface Props { queryParamKey?: string; } -export const DEFAULT_REPLAY_LIST_SORT = '-started_at'; -const DEFAULT_DECODED_REPLAY_SORT = decodeSorts(DEFAULT_REPLAY_LIST_SORT).at(0); +const DECODED_DEFAULT_REPLAY_LIST_SORT: Sort = {field: 'started_at', kind: 'desc'}; +export const DEFAULT_REPLAY_LIST_SORT = encodeSort(DECODED_DEFAULT_REPLAY_LIST_SORT); export default function useReplayTableSort({ - defaultSort = DEFAULT_DECODED_REPLAY_SORT, + defaultSort = DECODED_DEFAULT_REPLAY_LIST_SORT, queryParamKey = 'sort', }: Props = {}) { const organization = useOrganization(); @@ -30,7 +30,7 @@ export default function useReplayTableSort({ const newSort = { field: key, kind: - key === sortType?.field ? (sortType?.kind === 'asc' ? 'desc' : 'asc') : 'desc', + key === sortType.field ? (sortType.kind === 'asc' ? 'desc' : 'asc') : 'desc', } satisfies Sort; setParamValue(encodeSort(newSort)); diff --git a/static/app/utils/replays/hooks/useReplayList.tsx b/static/app/utils/replays/hooks/useReplayList.tsx index 6a4affd282f2ea..c69c40428ae741 100644 --- a/static/app/utils/replays/hooks/useReplayList.tsx +++ b/static/app/utils/replays/hooks/useReplayList.tsx @@ -25,7 +25,7 @@ type State = Awaited> & {isFetching: boolean} type Result = State; /** - * @deprecated due to its reliance on EventView which is considered bad practice + * @deprecated due to its reliance on EventView which is unpleasant to work with * Use useApiQuery instead */ function useReplayList({