Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/heavy-carpets-divide.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
---
"@tanstack/query-devtools": patch
---

Fix devtools UI state (selected query/mutation, panel width, offline mock toggle, and query/mutation cache subscriptions) leaking between independently mounted devtools instances. Selecting a query, resizing a panel, or mocking offline behavior in one devtools instance no longer affects another instance mounted on a different `QueryClient`.
65 changes: 41 additions & 24 deletions packages/query-devtools/src/Devtools.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -51,7 +51,13 @@ import {
XCircle,
} from './icons'
import Explorer from './Explorer'
import { usePiPWindow, useQueryDevtoolsContext, useTheme } from './contexts'
import {
DevtoolsInstanceProvider,
useDevtoolsInstanceContext,
usePiPWindow,
useQueryDevtoolsContext,
useTheme,
} from './contexts'
import {
BUTTON_POSITION,
DEFAULT_HEIGHT,
Expand All@@ -78,7 +84,7 @@ import type {
QueryCacheNotifyEvent,
} from '@tanstack/query-core'
import type { StorageObject, StorageSetter } from '@solid-primitives/storage'
import type { Accessor, Component, JSX, Setter } from 'solid-js'
import type { Accessor, Component, JSX } from 'solid-js'

interface DevtoolsPanelProps {
localStore: StorageObject<string>
Expand All@@ -98,20 +104,20 @@ interface QueryStatusProps {
count: number
}

const [selectedQueryHash, setSelectedQueryHash] = createSignal<string | null>(
null,
)
const [selectedMutationId, setSelectedMutationId] = createSignal<number | null>(
null,
)
const [panelWidth, setPanelWidth] = createSignal(0)
const [offline, setOffline] = createSignal(false)

export type DevtoolsComponentType = Component<QueryDevtoolsProps> & {
shadowDOMTarget?: ShadowRoot
}

export const Devtools: Component<DevtoolsPanelProps> = (props) => {
return (
<DevtoolsInstanceProvider>
<DevtoolsImpl {...props} />
</DevtoolsInstanceProvider>
)
}

const DevtoolsImpl: Component<DevtoolsPanelProps> = (props) => {
const { setOffline } = useDevtoolsInstanceContext()
const theme = useTheme()
const css = useQueryDevtoolsContext().shadowDOMTarget
? goober.css.bind({ target: useQueryDevtoolsContext().shadowDOMTarget })
Expand DownExpand Up@@ -281,6 +287,7 @@ export const Devtools: Component<DevtoolsPanelProps> = (props) => {
const PiPPanel: Component<{
children: JSX.Element
}> = (props) => {
const { panelWidth, setPanelWidth } = useDevtoolsInstanceContext()
const pip = usePiPWindow()
const theme = useTheme()
const css = useQueryDevtoolsContext().shadowDOMTarget
Expand DownExpand Up@@ -351,6 +358,7 @@ const PiPPanel: Component<{
export const ParentPanel: Component<{
children: JSX.Element
}> = (props) => {
const { panelWidth, setPanelWidth } = useDevtoolsInstanceContext()
const theme = useTheme()
const css = useQueryDevtoolsContext().shadowDOMTarget
? goober.css.bind({ target: useQueryDevtoolsContext().shadowDOMTarget })
Expand DownExpand Up@@ -408,6 +416,8 @@ export const ParentPanel: Component<{
}

const DraggablePanel: Component<DevtoolsPanelProps> = (props) => {
const { panelWidth, setPanelWidth, setSelectedQueryHash } =
useDevtoolsInstanceContext()
const theme = useTheme()
const css = useQueryDevtoolsContext().shadowDOMTarget
? goober.css.bind({ target: useQueryDevtoolsContext().shadowDOMTarget })
Expand DownExpand Up@@ -672,6 +682,14 @@ const DraggablePanel: Component<DevtoolsPanelProps> = (props) => {
}

export const ContentView: Component<ContentViewProps> = (props) => {
const {
panelWidth,
offline,
selectedQueryHash,
selectedMutationId,
setSelectedQueryHash,
setSelectedMutationId,
} = useDevtoolsInstanceContext()
setupQueryCacheSubscription()
setupMutationCacheSubscription()
let containerRef!: HTMLDivElement
Expand DownExpand Up@@ -1372,6 +1390,8 @@ export const ContentView: Component<ContentViewProps> = (props) => {
}

const QueryRow: Component<{ query: Query }> = (props) => {
const { selectedQueryHash, setSelectedQueryHash } =
useDevtoolsInstanceContext()
const theme = useTheme()
const css = useQueryDevtoolsContext().shadowDOMTarget
? goober.css.bind({ target: useQueryDevtoolsContext().shadowDOMTarget })
Expand DownExpand Up@@ -1481,6 +1501,8 @@ const QueryRow: Component<{ query: Query }> = (props) => {
}

const MutationRow: Component<{ mutation: Mutation }> = (props) => {
const { selectedMutationId, setSelectedMutationId } =
useDevtoolsInstanceContext()
const theme = useTheme()
const css = useQueryDevtoolsContext().shadowDOMTarget
? goober.css.bind({ target: useQueryDevtoolsContext().shadowDOMTarget })
Expand DownExpand Up@@ -1722,6 +1744,7 @@ const MutationStatusCount: Component = () => {
}

const QueryStatus: Component<QueryStatusProps> = (props) => {
const { panelWidth, selectedQueryHash } = useDevtoolsInstanceContext()
const theme = useTheme()
const css = useQueryDevtoolsContext().shadowDOMTarget
? goober.css.bind({ target: useQueryDevtoolsContext().shadowDOMTarget })
Expand DownExpand Up@@ -1837,6 +1860,8 @@ const QueryStatus: Component<QueryStatusProps> = (props) => {
}

const QueryDetails = () => {
const { selectedQueryHash, setSelectedQueryHash } =
useDevtoolsInstanceContext()
const theme = useTheme()
const css = useQueryDevtoolsContext().shadowDOMTarget
? goober.css.bind({ target: useQueryDevtoolsContext().shadowDOMTarget })
Expand DownExpand Up@@ -2382,6 +2407,7 @@ const QueryDetails = () => {
}

const MutationDetails = () => {
const { selectedMutationId } = useDevtoolsInstanceContext()
const theme = useTheme()
const css = useQueryDevtoolsContext().shadowDOMTarget
? goober.css.bind({ target: useQueryDevtoolsContext().shadowDOMTarget })
Expand DownExpand Up@@ -2569,15 +2595,8 @@ const MutationDetails = () => {
)
}

const queryCacheMap = new Map<
(q: Accessor<QueryCache>) => any,
{
setter: Setter<any>
shouldUpdate: (event: QueryCacheNotifyEvent) => boolean
}
>()

const setupQueryCacheSubscription = () => {
const { queryCacheMap } = useDevtoolsInstanceContext()
const queryCache = createMemo(() => {
const client = useQueryDevtoolsContext().client
return client.getQueryCache()
Expand DownExpand Up@@ -2605,6 +2624,7 @@ const createSubscribeToQueryCacheBatcher = <T,>(
equalityCheck: boolean = true,
shouldUpdate: (event: QueryCacheNotifyEvent) => boolean = () => true,
) => {
const { queryCacheMap } = useDevtoolsInstanceContext()
const queryCache = createMemo(() => {
const client = useQueryDevtoolsContext().client
return client.getQueryCache()
Expand All@@ -2631,12 +2651,8 @@ const createSubscribeToQueryCacheBatcher = <T,>(
return value
}

const mutationCacheMap = new Map<
(q: Accessor<MutationCache>) => any,
Setter<any>
>()

const setupMutationCacheSubscription = () => {
const { mutationCacheMap } = useDevtoolsInstanceContext()
const mutationCache = createMemo(() => {
const client = useQueryDevtoolsContext().client
return client.getMutationCache()
Expand All@@ -2662,6 +2678,7 @@ const createSubscribeToMutationCacheBatcher = <T,>(
callback: (queryCache: Accessor<MutationCache>) => Exclude<T, Function>,
equalityCheck: boolean = true,
) => {
const { mutationCacheMap } = useDevtoolsInstanceContext()
const mutationCache = createMemo(() => {
const client = useQueryDevtoolsContext().client
return client.getMutationCache()
Expand Down
25 changes: 16 additions & 9 deletions packages/query-devtools/src/DevtoolsPanelComponent.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,7 +3,12 @@ import { createMemo } from 'solid-js'
import { ContentView, ParentPanel } from './Devtools'
import { getPreferredColorScheme } from './utils'
import { THEME_PREFERENCE } from './constants'
import { PiPProvider, QueryDevtoolsContext, ThemeContext } from './contexts'
import {
DevtoolsInstanceProvider,
PiPProvider,
QueryDevtoolsContext,
ThemeContext,
} from './contexts'
import type { Theme } from './contexts'
import type { DevtoolsComponentType } from './Devtools'

Expand All@@ -30,14 +35,16 @@ const DevtoolsPanelComponent: DevtoolsComponentType = (props) => {
setLocalStore={setLocalStore}
>
<ThemeContext.Provider value={theme}>
<ParentPanel>
<ContentView
localStore={localStore}
setLocalStore={setLocalStore}
onClose={props.onClose}
showPanelViewOnly
/>
</ParentPanel>
<DevtoolsInstanceProvider>
<ParentPanel>
<ContentView
localStore={localStore}
setLocalStore={setLocalStore}
onClose={props.onClose}
showPanelViewOnly
/>
</ParentPanel>
</DevtoolsInstanceProvider>
</ThemeContext.Provider>
</PiPProvider>
</QueryDevtoolsContext.Provider>
Expand Down
Loading