Skip to content

Commit f8ad973

Browse files
toofffardeora
andauthored
feat(react-query-dev-tools): Add ReactQueryDevToolsPanel support (#7788)
* feat(react-query-dev-tools): Add ReactQueryDevToolsPanel support Devtools Embedded Support is finally here! Embedded Mode will embed the devtools as a regular component in your application. You can style it however you'd like after that! --------- Co-authored-by: Aryan Deora <adeora@iu.edu>
1 parent 8af7272 commit f8ad973

30 files changed

+1042
-352
lines changed

docs/config.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -929,6 +929,10 @@
929929
{
930930
"label": "Shadow DOM",
931931
"to": "framework/react/examples/shadow-dom"
932+
},
933+
{
934+
"label": "Devtools Embedded Panel",
935+
"to": "framework/react/examples/devtools-panel"
932936
}
933937
]
934938
},

docs/framework/react/devtools.md

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,50 @@ function App() {
8383
- The position of the React Query devtools panel
8484
- `client?: QueryClient`,
8585
- Use this to use a custom QueryClient. Otherwise, the one from the nearest context will be used.
86-
- `errorTypes?: { name: string; initializer: (query: Query) => TError}`
86+
- `errorTypes?: { name: string; initializer: (query: Query) => TError}[]`
87+
- Use this to predefine some errors that can be triggered on your queries. Initializer will be called (with the specific query) when that error is toggled on from the UI. It must return an Error.
88+
- `styleNonce?: string`
89+
- Use this to pass a nonce to the style tag that is added to the document head. This is useful if you are using a Content Security Policy (CSP) nonce to allow inline styles.
90+
- `shadowDOMTarget?: ShadowRoot`
91+
- Default behavior will apply the devtool's styles to the head tag within the DOM.
92+
- Use this to pass a shadow DOM target to the devtools so that the styles will be applied within the shadow DOM instead of within the head tag in the light DOM.
93+
94+
## Embedded Mode
95+
96+
Embedded mode will show the development tools as a fixed element in your application, so you can use our panel in your own development tools.
97+
98+
Place the following code as high in your React app as you can. The closer it is to the root of the page, the better it will work!
99+
100+
```tsx
101+
import { ReactQueryDevtools } from '@tanstack/react-query-devtools'
102+
103+
function App() {
104+
const [isOpen, setIsOpen] = React.useState(false)
105+
106+
return (
107+
<QueryClientProvider client={queryClient}>
108+
{/* The rest of your application */}
109+
<button
110+
onClick={() => setIsOpen(!isOpen)}
111+
>{`${isOpen ? 'Close' : 'Open'} the devtools panel`}</button>
112+
{isOpen && <ReactQueryDevtoolsPanel onClose={() => setIsOpen(false)} />}
113+
</QueryClientProvider>
114+
)
115+
}
116+
```
117+
118+
### Options
119+
120+
- `style?: React.CSSProperties`
121+
- Custom styles for the devtools panel
122+
- Default: `{ height: '500px' }`
123+
- Example: `{ height: '100%' }`
124+
- Example: `{ height: '100%', width: '100%' }`
125+
- `onClose?: () => unknown`
126+
- Callback function that is called when the devtools panel is closed
127+
- `client?: QueryClient`,
128+
- Use this to use a custom QueryClient. Otherwise, the one from the nearest context will be used.
129+
- `errorTypes?: { name: string; initializer: (query: Query) => TError}[]`
87130
- Use this to predefine some errors that can be triggered on your queries. Initializer will be called (with the specific query) when that error is toggled on from the UI. It must return an Error.
88131
- `styleNonce?: string`
89132
- Use this to pass a nonce to the style tag that is added to the document head. This is useful if you are using a Content Security Policy (CSP) nonce to allow inline styles.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"extends": ["plugin:react/jsx-runtime", "plugin:react-hooks/recommended"]
3+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2+
3+
# dependencies
4+
/node_modules
5+
/.pnp
6+
.pnp.js
7+
8+
# testing
9+
/coverage
10+
11+
# production
12+
/build
13+
14+
pnpm-lock.yaml
15+
yarn.lock
16+
package-lock.json
17+
18+
# misc
19+
.DS_Store
20+
.env.local
21+
.env.development.local
22+
.env.test.local
23+
.env.production.local
24+
25+
npm-debug.log*
26+
yarn-debug.log*
27+
yarn-error.log*
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Example
2+
3+
To run this example:
4+
5+
- `npm install`
6+
- `npm run dev`
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8" />
5+
<link rel="icon" type="image/svg+xml" href="/emblem-light.svg" />
6+
<meta name="viewport" content="width=device-width, initial-scale=1" />
7+
<meta name="theme-color" content="#000000" />
8+
9+
<title>TanStack Query React Devtools Panel Example App</title>
10+
</head>
11+
<body>
12+
<noscript>You need to enable JavaScript to run this app.</noscript>
13+
<div id="root"></div>
14+
<script type="module" src="/src/index.tsx"></script>
15+
</body>
16+
</html>
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"name": "@tanstack/query-example-react-devtools-panel",
3+
"private": true,
4+
"type": "module",
5+
"scripts": {
6+
"dev": "vite",
7+
"build": "vite build",
8+
"preview": "vite preview"
9+
},
10+
"dependencies": {
11+
"@tanstack/react-query": "^5.53.2",
12+
"@tanstack/react-query-devtools": "^5.53.2",
13+
"react": "19.0.0-rc-4c2e457c7c-20240522",
14+
"react-dom": "19.0.0-rc-4c2e457c7c-20240522"
15+
},
16+
"devDependencies": {
17+
"@vitejs/plugin-react": "^4.3.1",
18+
"typescript": "5.3.3",
19+
"vite": "^5.3.5"
20+
}
21+
}
Lines changed: 13 additions & 0 deletions
Loading
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import React from 'react'
2+
import ReactDOM from 'react-dom/client'
3+
import {
4+
QueryClient,
5+
QueryClientProvider,
6+
useQuery,
7+
} from '@tanstack/react-query'
8+
import { ReactQueryDevtoolsPanel } from '@tanstack/react-query-devtools'
9+
10+
const queryClient = new QueryClient()
11+
12+
export default function App() {
13+
const [isOpen, setIsOpen] = React.useState(false)
14+
15+
return (
16+
<QueryClientProvider client={queryClient}>
17+
<Example />
18+
<button
19+
onClick={() => setIsOpen(!isOpen)}
20+
>{`${isOpen ? 'Close' : 'Open'} the devtools panel`}</button>
21+
{isOpen && <ReactQueryDevtoolsPanel onClose={() => setIsOpen(false)} />}
22+
</QueryClientProvider>
23+
)
24+
}
25+
26+
function Example() {
27+
const { isPending, error, data, isFetching } = useQuery({
28+
queryKey: ['repoData'],
29+
queryFn: async () => {
30+
const response = await fetch(
31+
'https://api.github.com/repos/TanStack/query',
32+
)
33+
return await response.json()
34+
},
35+
})
36+
37+
if (isPending) return 'Loading...'
38+
39+
if (error) return 'An error has occurred: ' + error.message
40+
41+
return (
42+
<div
43+
style={{
44+
paddingBottom: 20,
45+
}}
46+
>
47+
<h1>{data.full_name}</h1>
48+
<p>{data.description}</p>
49+
<strong>👀 {data.subscribers_count}</strong>{' '}
50+
<strong>{data.stargazers_count}</strong>{' '}
51+
<strong>🍴 {data.forks_count}</strong>
52+
<div>{isFetching ? 'Updating...' : ''}</div>
53+
</div>
54+
)
55+
}
56+
57+
const rootElement = document.getElementById('root') as HTMLElement
58+
ReactDOM.createRoot(rootElement).render(<App />)
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
"compilerOptions": {
3+
"target": "ES2020",
4+
"useDefineForClassFields": true,
5+
"lib": ["ES2020", "DOM", "DOM.Iterable"],
6+
"module": "ESNext",
7+
"skipLibCheck": true,
8+
9+
/* Bundler mode */
10+
"moduleResolution": "Bundler",
11+
"allowImportingTsExtensions": true,
12+
"resolveJsonModule": true,
13+
"isolatedModules": true,
14+
"noEmit": true,
15+
"jsx": "react-jsx",
16+
17+
/* Linting */
18+
"strict": true,
19+
"noUnusedLocals": true,
20+
"noUnusedParameters": true,
21+
"noFallthroughCasesInSwitch": true
22+
},
23+
"include": ["src", "eslint.config.js"]
24+
}

0 commit comments

Comments
 (0)