From 47ff0b6560e375945ae28d3942401d7a7422c1ed Mon Sep 17 00:00:00 2001 From: Wonsuk Choi Date: Tue, 29 Sep 2026 10:46:03 +0900 Subject: [PATCH] fix(react-query-devtools): create the devtools instance lazily with 'useState' initializer instead of on every render --- .changeset/lazy-devtools-instance.md | 5 +++ .../src/ReactQueryDevtools.tsx | 29 ++++++++--------- .../src/ReactQueryDevtoolsPanel.tsx | 31 ++++++++++--------- .../src/__tests__/ReactQueryDevtools.test.tsx | 10 ++++++ .../ReactQueryDevtoolsPanel.test.tsx | 10 ++++++ 5 files changed, 56 insertions(+), 29 deletions(-) create mode 100644 .changeset/lazy-devtools-instance.md diff --git a/.changeset/lazy-devtools-instance.md b/.changeset/lazy-devtools-instance.md new file mode 100644 index 00000000000..57aae42b393 --- /dev/null +++ b/.changeset/lazy-devtools-instance.md @@ -0,0 +1,5 @@ +--- +'@tanstack/react-query-devtools': patch +--- + +fix(react-query-devtools): create the devtools instance only once instead of on every render diff --git a/packages/react-query-devtools/src/ReactQueryDevtools.tsx b/packages/react-query-devtools/src/ReactQueryDevtools.tsx index 9dba2d1551f..25784030264 100644 --- a/packages/react-query-devtools/src/ReactQueryDevtools.tsx +++ b/packages/react-query-devtools/src/ReactQueryDevtools.tsx @@ -73,20 +73,21 @@ export function ReactQueryDevtools( theme, } = props const [devtools] = React.useState( - new TanstackQueryDevtools({ - client: queryClient, - queryFlavor: 'React Query', - version: '5', - onlineManager, - buttonPosition, - position, - initialIsOpen, - errorTypes, - styleNonce, - shadowDOMTarget, - hideDisabledQueries, - theme, - }), + () => + new TanstackQueryDevtools({ + client: queryClient, + queryFlavor: 'React Query', + version: '5', + onlineManager, + buttonPosition, + position, + initialIsOpen, + errorTypes, + styleNonce, + shadowDOMTarget, + hideDisabledQueries, + theme, + }), ) React.useEffect(() => { diff --git a/packages/react-query-devtools/src/ReactQueryDevtoolsPanel.tsx b/packages/react-query-devtools/src/ReactQueryDevtoolsPanel.tsx index 91faad64a5a..825dbae2203 100644 --- a/packages/react-query-devtools/src/ReactQueryDevtoolsPanel.tsx +++ b/packages/react-query-devtools/src/ReactQueryDevtoolsPanel.tsx @@ -60,21 +60,22 @@ export function ReactQueryDevtoolsPanel( theme, } = props const [devtools] = React.useState( - new TanstackQueryDevtoolsPanel({ - client: queryClient, - queryFlavor: 'React Query', - version: '5', - onlineManager, - buttonPosition: 'bottom-left', - position: 'bottom', - initialIsOpen: true, - errorTypes, - styleNonce, - shadowDOMTarget, - onClose: props.onClose, - hideDisabledQueries, - theme, - }), + () => + new TanstackQueryDevtoolsPanel({ + client: queryClient, + queryFlavor: 'React Query', + version: '5', + onlineManager, + buttonPosition: 'bottom-left', + position: 'bottom', + initialIsOpen: true, + errorTypes, + styleNonce, + shadowDOMTarget, + onClose: props.onClose, + hideDisabledQueries, + theme, + }), ) React.useEffect(() => { diff --git a/packages/react-query-devtools/src/__tests__/ReactQueryDevtools.test.tsx b/packages/react-query-devtools/src/__tests__/ReactQueryDevtools.test.tsx index a55b98970b5..85232ce5f5e 100644 --- a/packages/react-query-devtools/src/__tests__/ReactQueryDevtools.test.tsx +++ b/packages/react-query-devtools/src/__tests__/ReactQueryDevtools.test.tsx @@ -149,6 +149,16 @@ describe('ReactQueryDevtools', () => { ) }) + it('should create the devtools instance only once across re-renders', () => { + const { rerender } = render( + , + ) + + rerender() + + expect(TanstackQueryDevtools).toHaveBeenCalledTimes(1) + }) + it('should forward a "buttonPosition" change to the devtools instance after mount', () => { const { rerender } = render( , diff --git a/packages/react-query-devtools/src/__tests__/ReactQueryDevtoolsPanel.test.tsx b/packages/react-query-devtools/src/__tests__/ReactQueryDevtoolsPanel.test.tsx index bdee2f39e9a..c530a1c15dc 100644 --- a/packages/react-query-devtools/src/__tests__/ReactQueryDevtoolsPanel.test.tsx +++ b/packages/react-query-devtools/src/__tests__/ReactQueryDevtoolsPanel.test.tsx @@ -142,6 +142,16 @@ describe('ReactQueryDevtoolsPanel', () => { ) }) + it('should create the devtools instance only once across re-renders', () => { + const { rerender } = render( + , + ) + + rerender() + + expect(TanstackQueryDevtoolsPanel).toHaveBeenCalledTimes(1) + }) + it('should preserve the default container height when "style" omits "height"', () => { const { container } = render(