|
1 | 1 | import {Fragment, useMemo} from 'react'; |
2 | 2 | import styled from '@emotion/styled'; |
| 3 | +import {parseAsBoolean, parseAsStringLiteral, useQueryState} from 'nuqs'; |
3 | 4 |
|
4 | 5 | import {ExternalLink, Link} from 'sentry/components/core/link'; |
5 | 6 | import {TabList, Tabs} from 'sentry/components/core/tabs'; |
6 | 7 | import FieldGroup from 'sentry/components/forms/fieldGroup'; |
7 | 8 | import TextCopyInput from 'sentry/components/textCopyInput'; |
8 | 9 | import {t, tct} from 'sentry/locale'; |
9 | 10 | import type {ProjectKey} from 'sentry/types/project'; |
10 | | -import {decodeScalar} from 'sentry/utils/queryString'; |
11 | 11 | import {useLocation} from 'sentry/utils/useLocation'; |
12 | | -import {useNavigate} from 'sentry/utils/useNavigate'; |
13 | 12 | import {OtlpTab} from 'sentry/views/settings/project/projectKeys/credentials/otlp'; |
14 | 13 | import {VercelTab} from 'sentry/views/settings/project/projectKeys/credentials/vercel'; |
15 | 14 |
|
@@ -180,9 +179,7 @@ function ProjectKeyCredentials({ |
180 | 179 | showUnreal = true, |
181 | 180 | }: Props) { |
182 | 181 | const location = useLocation(); |
183 | | - const navigate = useNavigate(); |
184 | 182 |
|
185 | | - // Calculate available tabs based on props |
186 | 183 | const availableTabs = useMemo<TabConfig[]>(() => { |
187 | 184 | const tabs: TabConfig[] = [ |
188 | 185 | { |
@@ -229,29 +226,17 @@ function ProjectKeyCredentials({ |
229 | 226 | showProjectId, |
230 | 227 | ]); |
231 | 228 |
|
232 | | - // Get showDeprecatedDsn from query params |
233 | | - const showDeprecatedDsn = decodeScalar(location?.query?.showDeprecated) === 'true'; |
| 229 | + const [showDeprecatedDsn] = useQueryState('showDeprecated', parseAsBoolean); |
234 | 230 |
|
235 | | - // Get current tab from query params, defaulting to first available |
236 | | - const getCurrentTab = (): TabValue => { |
237 | | - const queryTab = decodeScalar(location?.query?.tab); |
238 | | - const validTabs = availableTabs.map(tab => tab.key); |
239 | | - return validTabs.includes(queryTab as TabValue) |
240 | | - ? (queryTab as TabValue) |
241 | | - : (availableTabs[0]?.key ?? 'otlp'); |
242 | | - }; |
243 | | - |
244 | | - const activeTab = getCurrentTab(); |
| 231 | + const tabParser = useMemo( |
| 232 | + () => ({ |
| 233 | + ...parseAsStringLiteral(availableTabs.map(tab => tab.key)), |
| 234 | + defaultValue: availableTabs[0]?.key ?? 'otlp', |
| 235 | + }), |
| 236 | + [availableTabs] |
| 237 | + ); |
245 | 238 |
|
246 | | - const handleTabChange = (newTab: TabValue) => { |
247 | | - navigate({ |
248 | | - pathname: location.pathname, |
249 | | - query: { |
250 | | - ...location.query, |
251 | | - tab: newTab, |
252 | | - }, |
253 | | - }); |
254 | | - }; |
| 239 | + const [activeTab, setActiveTab] = useQueryState('tab', tabParser); |
255 | 240 |
|
256 | 241 | const renderTabContent = () => { |
257 | 242 | switch (activeTab) { |
@@ -309,7 +294,6 @@ function ProjectKeyCredentials({ |
309 | 294 | link: showDsn ? ( |
310 | 295 | <Link |
311 | 296 | to={{ |
312 | | - ...location, |
313 | 297 | query: { |
314 | 298 | ...location.query, |
315 | 299 | showDeprecated: showDeprecatedDsn ? undefined : 'true', |
@@ -365,7 +349,7 @@ function ProjectKeyCredentials({ |
365 | 349 |
|
366 | 350 | {availableTabs.length > 0 && ( |
367 | 351 | <Fragment> |
368 | | - <Tabs value={activeTab} onChange={handleTabChange}> |
| 352 | + <Tabs value={activeTab} onChange={setActiveTab}> |
369 | 353 | <TabList> |
370 | 354 | {availableTabs.map(tab => ( |
371 | 355 | <TabList.Item key={tab.key}>{tab.label}</TabList.Item> |
|
0 commit comments