Skip to content

Commit 9feb9c3

Browse files
Feat/dettached mode but it works (#70)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
1 parent 6816bae commit 9feb9c3

File tree

22 files changed

+549
-120
lines changed

22 files changed

+549
-120
lines changed

.changeset/fruity-teams-lick.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
'@tanstack/react-devtools': minor
3+
'@tanstack/solid-devtools': minor
4+
'@tanstack/devtools-event-bus': minor
5+
'@tanstack/devtools': minor
6+
---
7+
8+
removed CJS support, added detached mode to devtools

docs/vite-plugin.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ export default {
7171

7272
### editor
7373

74-
> [!IMPORTANT] `editor` is only needed for editors that are NOT VS Code, by default this works OOTB with VS Code.
74+
> [!IMPORTANT] `editor` is only needed for editors that are NOT VS Code, by default this works OOTB with VS Code. If you don't have `code` available in your terminal you need to set it up though, if you don't know how to do that you can follow this guide: https://stackoverflow.com/questions/29955500/code-is-not-working-in-on-the-command-line-for-visual-studio-code-on-os-x-ma
7575
7676

7777
The open in editor configuration which has two fields, `name` and `open`,

examples/react/basic/src/index.tsx

Lines changed: 179 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,141 @@
11
import { createRoot } from 'react-dom/client'
2+
import { createContext, useContext, useState } from 'react'
3+
import { createPortal } from 'react-dom'
4+
import {
5+
QueryClient,
6+
QueryClientProvider,
7+
useQuery,
8+
useQueryClient,
9+
} from '@tanstack/react-query'
210
import Devtools from './setup'
311
import { queryPlugin } from './plugin'
412
import { Button } from './button'
513
import { Feature } from './feature'
614

15+
const queryClient = new QueryClient({
16+
defaultOptions: {
17+
queries: {
18+
gcTime: 1000 * 60 * 60 * 24, // 24 hours
19+
},
20+
},
21+
})
22+
23+
type Post = {
24+
id: number
25+
title: string
26+
body: string
27+
}
28+
29+
function Posts({
30+
setPostId,
31+
}: {
32+
setPostId: React.Dispatch<React.SetStateAction<number>>
33+
}) {
34+
const queryClient = useQueryClient()
35+
const { status, data, error, isFetching } = usePosts()
36+
37+
return (
38+
<div>
39+
<h1>Posts</h1>
40+
<div>
41+
{status === 'pending' ? (
42+
'Loading...'
43+
) : status === 'error' ? (
44+
<span>Error: {error.message}</span>
45+
) : (
46+
<>
47+
<div>
48+
{data.map((post) => (
49+
<p key={post.id}>
50+
<a
51+
onClick={() => setPostId(post.id)}
52+
href="#"
53+
style={
54+
// We can access the query data here to show bold links for
55+
// ones that are cached
56+
queryClient.getQueryData(['post', post.id])
57+
? {
58+
fontWeight: 'bold',
59+
color: 'green',
60+
}
61+
: {}
62+
}
63+
>
64+
{post.title}
65+
</a>
66+
</p>
67+
))}
68+
</div>
69+
<div>{isFetching ? 'Background Updating...' : ' '}</div>
70+
</>
71+
)}
72+
</div>
73+
</div>
74+
)
75+
}
76+
77+
const getPostById = async (id: number): Promise<Post> => {
78+
const response = await fetch(
79+
`https://jsonplaceholder.typicode.com/posts/${id}`,
80+
)
81+
return await response.json()
82+
}
83+
84+
function usePost(postId: number) {
85+
return useQuery({
86+
queryKey: ['post', postId],
87+
queryFn: () => getPostById(postId),
88+
enabled: !!postId,
89+
})
90+
}
91+
92+
function Post({
93+
postId,
94+
setPostId,
95+
}: {
96+
postId: number
97+
setPostId: React.Dispatch<React.SetStateAction<number>>
98+
}) {
99+
const { status, data, error, isFetching } = usePost(postId)
100+
101+
return (
102+
<div>
103+
<div>
104+
<a onClick={() => setPostId(-1)} href="#">
105+
Back
106+
</a>
107+
</div>
108+
{!postId || status === 'pending' ? (
109+
'Loading...'
110+
) : status === 'error' ? (
111+
<span>Error: {error.message}</span>
112+
) : (
113+
<>
114+
<h1>{data.title}</h1>
115+
<div>
116+
<p>{data.body}</p>
117+
</div>
118+
<div>{isFetching ? 'Background Updating...' : ' '}</div>
119+
</>
120+
)}
121+
</div>
122+
)
123+
}
124+
function usePosts() {
125+
return useQuery({
126+
queryKey: ['posts'],
127+
queryFn: async (): Promise<Array<Post>> => {
128+
const response = await fetch('https://jsonplaceholder.typicode.com/posts')
129+
return await response.json()
130+
},
131+
})
132+
}
133+
134+
const Context = createContext<{
135+
count: number
136+
setCount: (count: number) => void
137+
}>({ count: 0, setCount: () => {} })
138+
7139
setTimeout(() => {
8140
queryPlugin.emit('test', {
9141
title: 'Test Event',
@@ -16,13 +148,56 @@ queryPlugin.on('test', (event) => {
16148
console.log('Received test event:', event)
17149
})
18150

151+
function Mounted() {
152+
const c = useContext(Context)
153+
console.log(c)
154+
return (
155+
<p
156+
onClick={() => {
157+
c.setCount(c.count + 1)
158+
}}
159+
>
160+
{c.count}
161+
<hr />
162+
</p>
163+
)
164+
}
165+
19166
function App() {
167+
const [state, setState] = useState(1)
168+
const [win, setWin] = useState<Window | null>(null)
169+
const [postId, setPostId] = useState(-1)
20170
return (
21171
<div>
22-
<h1>TanStack Devtools React Basic Example</h1>
23-
<Button>Click me</Button>
24-
<Feature />
25-
<Devtools />
172+
<Context.Provider value={{ count: state, setCount: setState }}>
173+
<QueryClientProvider client={queryClient}>
174+
<p>
175+
As you visit the posts below, you will notice them in a loading
176+
state the first time you load them. However, after you return to
177+
this list and click on any posts you have already visited again, you
178+
will see them load instantly and background refresh right before
179+
your eyes!{' '}
180+
<strong>
181+
(You may need to throttle your network speed to simulate longer
182+
loading sequences)
183+
</strong>
184+
</p>
185+
{postId > -1 ? (
186+
<Post postId={postId} setPostId={setPostId} />
187+
) : (
188+
<Posts setPostId={setPostId} />
189+
)}
190+
<Devtools />
191+
</QueryClientProvider>
192+
<h1>TanStack Devtools React Basic Example</h1>
193+
current count: {state}
194+
<Button onClick={() => setState(state + 1)}>Click me</Button>
195+
<Button onClick={() => setWin(window.open('', '', 'popup'))}>
196+
Click me to open new window
197+
</Button>
198+
{win && createPortal(<Mounted />, win.document.body)}
199+
<Feature />
200+
</Context.Provider>
26201
</div>
27202
)
28203
}

examples/react/basic/src/setup.tsx

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
21
import { ReactQueryDevtoolsPanel } from '@tanstack/react-query-devtools'
32
import { TanStackRouterDevtoolsPanel } from '@tanstack/react-router-devtools'
43
import {
@@ -57,26 +56,22 @@ const routeTree = rootRoute.addChildren([indexRoute, aboutRoute])
5756

5857
const router = createRouter({ routeTree })
5958

60-
const queryClient = new QueryClient()
61-
6259
export default function DevtoolsExample() {
6360
return (
6461
<>
65-
<QueryClientProvider client={queryClient}>
66-
<TanStackDevtools
67-
plugins={[
68-
{
69-
name: 'TanStack Query',
70-
render: <ReactQueryDevtoolsPanel />,
71-
},
72-
{
73-
name: 'TanStack Router',
74-
render: <TanStackRouterDevtoolsPanel router={router} />,
75-
},
76-
]}
77-
/>
78-
<RouterProvider router={router} />
79-
</QueryClientProvider>
62+
<TanStackDevtools
63+
plugins={[
64+
{
65+
name: 'TanStack Query',
66+
render: <ReactQueryDevtoolsPanel />,
67+
},
68+
{
69+
name: 'TanStack Router',
70+
render: <TanStackRouterDevtoolsPanel router={router} />,
71+
},
72+
]}
73+
/>
74+
<RouterProvider router={router} />
8075
</>
8176
)
8277
}

packages/devtools/package.json

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,12 @@
1919
],
2020
"type": "module",
2121
"types": "dist/esm/index.d.ts",
22-
"main": "dist/cjs/index.cjs",
2322
"module": "dist/esm/index.js",
2423
"exports": {
2524
".": {
2625
"import": {
2726
"types": "./dist/esm/index.d.ts",
2827
"default": "./dist/esm/index.js"
29-
},
30-
"require": {
31-
"types": "./dist/cjs/index.d.cts",
32-
"default": "./dist/cjs/index.cjs"
3328
}
3429
},
3530
"./package.json": "./package.json"

packages/devtools/src/components/main-panel.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import clsx from 'clsx'
22
import { useDevtoolsSettings, useHeight } from '../context/use-devtools-context'
33
import { useStyles } from '../styles/use-styles'
44
import { TANSTACK_DEVTOOLS } from '../utils/storage'
5+
import { usePiPWindow } from '../context/pip-context'
56
import type { Accessor, JSX } from 'solid-js'
67

78
export const MainPanel = (props: {
@@ -12,14 +13,18 @@ export const MainPanel = (props: {
1213
const styles = useStyles()
1314
const { height } = useHeight()
1415
const { settings } = useDevtoolsSettings()
16+
const pip = usePiPWindow()
1517
return (
1618
<div
1719
id={TANSTACK_DEVTOOLS}
1820
style={{
19-
height: height() + 'px',
21+
height: pip().pipWindow ? '100vh' : height() + 'px',
2022
}}
2123
class={clsx(
22-
styles().devtoolsPanelContainer(settings().panelLocation),
24+
styles().devtoolsPanelContainer(
25+
settings().panelLocation,
26+
Boolean(pip().pipWindow),
27+
),
2328
styles().devtoolsPanelContainerAnimation(props.isOpen(), height()),
2429
styles().devtoolsPanelContainerVisibility(props.isOpen()),
2530
styles().devtoolsPanelContainerResizing(props.isResizing),
Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { createEffect, createSignal } from 'solid-js'
1+
import { createMemo } from 'solid-js'
22
import { useDevtoolsState } from '../context/use-devtools-context'
33
import { tabs } from '../tabs'
44
import { useStyles } from '../styles/use-styles'
@@ -7,14 +7,9 @@ import type { JSX } from 'solid-js'
77
export const TabContent = () => {
88
const { state } = useDevtoolsState()
99
const styles = useStyles()
10-
const [component, setComponent] = createSignal<JSX.Element | null>(
11-
tabs.find((t) => t.id === state().activeTab)?.component() || null,
10+
const component = createMemo<(() => JSX.Element) | null>(
11+
() => tabs.find((t) => t.id === state().activeTab)?.component || null,
1212
)
13-
createEffect(() => {
14-
setComponent(
15-
tabs.find((t) => t.id === state().activeTab)?.component() || null,
16-
)
17-
})
1813

19-
return <div class={styles().tabContent}>{component()}</div>
14+
return <div class={styles().tabContent}>{component()?.()}</div>
2015
}

0 commit comments

Comments
 (0)