From 2f2db63e84d601579d4bfce3da07ee0bf304038d Mon Sep 17 00:00:00 2001 From: "vscode.d" Date: Sun, 22 Mar 2026 08:29:36 +0000 Subject: [PATCH 1/2] fix(useTreeData): insert items into a child node with StrictMode --- .../dev/test-utils/src/renderOverride.tsx | 4 +- .../react-stately/src/data/useTreeData.ts | 2 +- .../test/data/useTreeData.test.js | 41 +++++++++++++++++++ 3 files changed, 44 insertions(+), 3 deletions(-) diff --git a/packages/dev/test-utils/src/renderOverride.tsx b/packages/dev/test-utils/src/renderOverride.tsx index 16992acf2c8..44f6f965697 100644 --- a/packages/dev/test-utils/src/renderOverride.tsx +++ b/packages/dev/test-utils/src/renderOverride.tsx @@ -25,11 +25,11 @@ function customRender(ui: Parameters[0], options?: Parameters reactTestingLibrary.renderHook(render, {wrapper: StrictModeWrapper, ...options}); export let actHook = reactTestingLibrary.act as typeof originalAct; if (!renderHook) { let rhtl = require('@testing-library/react-hooks'); - renderHook = rhtl.renderHook; + renderHook = (render, options) => rhtl.renderHook(render, {wrapper: StrictModeWrapper, ...options}); actHook = rhtl.act; } diff --git a/packages/react-stately/src/data/useTreeData.ts b/packages/react-stately/src/data/useTreeData.ts index 2efd5082eec..1d11b612a7f 100644 --- a/packages/react-stately/src/data/useTreeData.ts +++ b/packages/react-stately/src/data/useTreeData.ts @@ -261,7 +261,7 @@ export function useTreeData(options: TreeOptions): TreeData }, insert(parentKey: Key | null, index: number, ...values: T[]) { setItems(({items, nodeMap: originalMap}) => { - let {items: newNodes, nodeMap: newMap} = buildTree(values, originalMap, parentKey); + let {items: newNodes, nodeMap: newMap} = buildTree(values, new Map(originalMap), parentKey); // If parentKey is null, insert into the root. if (parentKey == null) { diff --git a/packages/react-stately/test/data/useTreeData.test.js b/packages/react-stately/test/data/useTreeData.test.js index 513d213c17b..187bd247d5d 100644 --- a/packages/react-stately/test/data/useTreeData.test.js +++ b/packages/react-stately/test/data/useTreeData.test.js @@ -69,6 +69,26 @@ describe('useTreeData', function () { expect(result.current.items[0].children[0].children[1].value).toEqual({name: 'Devon'}); expect(result.current.items[0].children[1]).toBe(initialResult.items[0].children[1]); expect(result.current.items[0].children[2]).toBe(initialResult.items[0].children[2]); + + ({result} = renderHook(() => useTreeData({initialItems: [], getChildren, getKey}))); + + expect(result.current.items).toHaveLength(0); + + act(() => { + result.current.insert(null, 0, {name: 'John'}); + }); + + expect(result.current.items).toHaveLength(1); + expect(result.current.items[0].value).toEqual({name: 'John'}); + + act(() => { + result.current.insert('John', 0, {name: 'Devon'}); + }); + + expect(result.current.items).toHaveLength(1); + expect(result.current.items[0].value).toEqual({name: 'John'}); + expect(result.current.items[0].children).toHaveLength(1); + expect(result.current.items[0].children[0].value).toEqual({name: 'Devon'}); }); it('should insert multiple items into a child node', function () { @@ -90,6 +110,27 @@ describe('useTreeData', function () { expect(result.current.items[0].children[0].children[2].value).toEqual({name: 'Danni'}); expect(result.current.items[0].children[1]).toBe(initialResult.items[0].children[1]); expect(result.current.items[0].children[2]).toBe(initialResult.items[0].children[2]); + + ({result} = renderHook(() => useTreeData({initialItems: [], getChildren, getKey}))); + + expect(result.current.items).toHaveLength(0); + + act(() => { + result.current.insert(null, 0, {name: 'John'}); + }); + + expect(result.current.items).toHaveLength(1); + expect(result.current.items[0].value).toEqual({name: 'John'}); + + act(() => { + result.current.insert('John', 0, {name: 'Devon'}, {name: 'Danni'}); + }); + + expect(result.current.items).toHaveLength(1); + expect(result.current.items[0].value).toEqual({name: 'John'}); + expect(result.current.items[0].children).toHaveLength(2); + expect(result.current.items[0].children[0].value).toEqual({name: 'Devon'}); + expect(result.current.items[0].children[1].value).toEqual({name: 'Danni'}); }); it('should insert an item into the root', function () { From 0666cc6995892d299b37d5967c12a9a1ade7e619 Mon Sep 17 00:00:00 2001 From: "vscode.d" Date: Sun, 22 Mar 2026 08:57:23 +0000 Subject: [PATCH 2/2] fix 17/16 --- packages/dev/test-utils/src/renderOverride.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/dev/test-utils/src/renderOverride.tsx b/packages/dev/test-utils/src/renderOverride.tsx index 44f6f965697..aa0de262dc4 100644 --- a/packages/dev/test-utils/src/renderOverride.tsx +++ b/packages/dev/test-utils/src/renderOverride.tsx @@ -27,7 +27,7 @@ let reactTestingLibrary = require('@testing-library/react'); // (i.e. renderHook is only in v13+ of testing library) export let renderHook: typeof originalRenderHook = (render, options) => reactTestingLibrary.renderHook(render, {wrapper: StrictModeWrapper, ...options}); export let actHook = reactTestingLibrary.act as typeof originalAct; -if (!renderHook) { +if (!reactTestingLibrary.renderHook) { let rhtl = require('@testing-library/react-hooks'); renderHook = (render, options) => rhtl.renderHook(render, {wrapper: StrictModeWrapper, ...options}); actHook = rhtl.act;