Skip to content

Commit e9ad034

Browse files
authored
[codex] Gate React Query devtools behind dev toggle (#14451)
1 parent 5c66f69 commit e9ad034

4 files changed

Lines changed: 88 additions & 2 deletions

File tree

packages/web/src/app/AppProviders.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
import { PersistGate } from 'redux-persist/integration/react'
1616
import { WagmiProvider } from 'wagmi'
1717

18+
import { REACT_QUERY_DEVTOOLS_KEY, useDevToggle } from 'hooks/useDevToggle'
1819
import { useIsMobile } from 'hooks/useIsMobile'
1920
import { env } from 'services/env'
2021
import { queryClient } from 'services/query-client'
@@ -41,6 +42,10 @@ type AppProvidersProps = {
4142

4243
export const AppProviders = ({ children }: AppProvidersProps) => {
4344
const isMobile = useIsMobile()
45+
const [reactQueryDevtoolsEnabled] = useDevToggle(
46+
REACT_QUERY_DEVTOOLS_KEY,
47+
false
48+
)
4449

4550
const [{ store, persistor }] = useState(() => {
4651
const theme = getTheme()
@@ -95,7 +100,7 @@ export const AppProviders = ({ children }: AppProvidersProps) => {
95100
</PersistGate>
96101
</ReduxProvider>
97102
</MediaProvider>
98-
<ReactQueryDevtools />
103+
{reactQueryDevtoolsEnabled ? <ReactQueryDevtools /> : null}
99104
</QueryClientProvider>
100105
</WagmiProvider>
101106
)
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import { useCallback, useEffect, useState } from 'react'
2+
3+
const CHANGE_EVENT = 'audius:dev-toggle-change'
4+
5+
const read = (key: string, defaultValue: boolean): boolean => {
6+
if (typeof window === 'undefined') return defaultValue
7+
8+
try {
9+
const raw = window.localStorage.getItem(key)
10+
if (raw === null) return defaultValue
11+
return raw === 'true'
12+
} catch {
13+
return defaultValue
14+
}
15+
}
16+
17+
export const useDevToggle = (
18+
key: string,
19+
defaultValue: boolean
20+
): [boolean, (next: boolean) => void] => {
21+
const [value, setValue] = useState(() => read(key, defaultValue))
22+
23+
useEffect(() => {
24+
const sync = (event: Event) => {
25+
if (event instanceof CustomEvent && event.detail?.key === key) {
26+
setValue(read(key, defaultValue))
27+
}
28+
29+
if (event instanceof StorageEvent && event.key === key) {
30+
setValue(read(key, defaultValue))
31+
}
32+
}
33+
34+
window.addEventListener(CHANGE_EVENT, sync)
35+
window.addEventListener('storage', sync)
36+
37+
return () => {
38+
window.removeEventListener(CHANGE_EVENT, sync)
39+
window.removeEventListener('storage', sync)
40+
}
41+
}, [key, defaultValue])
42+
43+
const set = useCallback(
44+
(next: boolean) => {
45+
try {
46+
window.localStorage.setItem(key, String(next))
47+
} catch {}
48+
49+
setValue(next)
50+
window.dispatchEvent(new CustomEvent(CHANGE_EVENT, { detail: { key } }))
51+
},
52+
[key]
53+
)
54+
55+
return [value, set]
56+
}
57+
58+
export const REACT_QUERY_DEVTOOLS_KEY = 'audius-react-query-devtools-enabled'

packages/web/src/pages/dev-tools/DevTools.tsx

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
IconShieldCheck,
1010
IconDashboard,
1111
IconFanClub,
12+
IconRefresh,
1213
IconUser,
1314
Paper,
1415
Text,
@@ -19,6 +20,7 @@ import { useNavigate } from 'react-router'
1920

2021
import { Header } from 'components/header/desktop/Header'
2122
import { Page } from 'components/page/Page'
23+
import { REACT_QUERY_DEVTOOLS_KEY, useDevToggle } from 'hooks/useDevToggle'
2224
import { env } from 'services/env'
2325

2426
import { messages } from './messages'
@@ -102,6 +104,8 @@ export const DevTools = () => {
102104
const dispatch = useDispatch()
103105
const navigate = useNavigate()
104106
const { onOpen: openCoinSuccessModal } = useCoinSuccessModal()
107+
const [reactQueryDevtoolsEnabled, setReactQueryDevtoolsEnabled] =
108+
useDevToggle(REACT_QUERY_DEVTOOLS_KEY, false)
105109

106110
const handleOpenFeatureFlags = () => {
107111
dispatch(
@@ -217,6 +221,20 @@ export const DevTools = () => {
217221
buttonText={messages.coinSuccessModalPreviewButton}
218222
onButtonClick={handleOpenCoinSuccessModalPreview}
219223
/>
224+
225+
<DevToolCard
226+
icon={IconRefresh}
227+
title={messages.reactQueryDevtoolsTitle}
228+
description={messages.reactQueryDevtoolsDescription}
229+
buttonText={
230+
reactQueryDevtoolsEnabled
231+
? messages.reactQueryDevtoolsDisable
232+
: messages.reactQueryDevtoolsEnable
233+
}
234+
onButtonClick={() =>
235+
setReactQueryDevtoolsEnabled(!reactQueryDevtoolsEnabled)
236+
}
237+
/>
220238
</Flex>
221239
</Box>
222240
</Page>

packages/web/src/pages/dev-tools/messages.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,5 +46,10 @@ export const messages = {
4646
coinSuccessModalPreviewTitle: 'Coin success modal',
4747
coinSuccessModalPreviewDescription:
4848
'Open the post-launch fan club success dialog with sample coin data (UI preview only).',
49-
coinSuccessModalPreviewButton: 'Open coin success modal'
49+
coinSuccessModalPreviewButton: 'Open coin success modal',
50+
reactQueryDevtoolsTitle: 'React Query Devtools',
51+
reactQueryDevtoolsDescription:
52+
'Show the floating React Query devtools button for inspecting queries, mutations, and cache state. Off by default.',
53+
reactQueryDevtoolsEnable: 'Show Devtools Button',
54+
reactQueryDevtoolsDisable: 'Hide Devtools Button'
5055
}

0 commit comments

Comments
 (0)