From 9ef3f9a7c2ea52778027fb61988f876b590b22b0 Mon Sep 17 00:00:00 2001 From: Emerson Hsieh Date: Thu, 30 Nov 2023 11:35:28 -0800 Subject: [PATCH] fix(react): trigger useComponentValue on deleted records (#1959) Co-authored-by: Kevin Ingersoll --- .changeset/tasty-balloons-collect.md | 5 +++++ packages/react/package.json | 4 ++-- packages/react/src/useComponentValue.test.ts | 22 ++++++++++++++++++++ packages/react/src/useComponentValue.ts | 2 +- 4 files changed, 30 insertions(+), 3 deletions(-) create mode 100644 .changeset/tasty-balloons-collect.md diff --git a/.changeset/tasty-balloons-collect.md b/.changeset/tasty-balloons-collect.md new file mode 100644 index 0000000000..d6401790b5 --- /dev/null +++ b/.changeset/tasty-balloons-collect.md @@ -0,0 +1,5 @@ +--- +"@latticexyz/react": patch +--- + +Fixed an issue where `useComponentValue` would not detect a change and re-render if the component value was immediately removed. diff --git a/packages/react/package.json b/packages/react/package.json index b91b309842..509ee260c6 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -19,8 +19,8 @@ "clean": "pnpm run clean:js", "clean:js": "rimraf dist", "dev": "tsup --watch", - "test": "tsc --noEmit && vitest --run", - "test:ci": "pnpm run test" + "test": "tsc --noEmit && vitest", + "test:ci": "tsc --noEmit && vitest --run" }, "dependencies": { "@latticexyz/recs": "workspace:*", diff --git a/packages/react/src/useComponentValue.test.ts b/packages/react/src/useComponentValue.test.ts index 6bb29e626d..30d7652be4 100644 --- a/packages/react/src/useComponentValue.test.ts +++ b/packages/react/src/useComponentValue.test.ts @@ -40,6 +40,11 @@ describe("useComponentValue", () => { removeComponent(Position, entity); }); expect(result.current).toBe(undefined); + + act(() => { + setComponent(Position, entity, { x: 0, y: 0 }); + }); + expect(result.current).toEqual({ x: 0, y: 0 }); }); it("should re-render only when Position changes for entity", () => { @@ -70,6 +75,23 @@ describe("useComponentValue", () => { expect(result.current).toBe(undefined); }); + it("should re-render when Position is removed", () => { + const entity = createEntity(world, [withValue(Position, { x: 1, y: 1 })]); + + const { result } = renderHook(() => useComponentValue(Position, entity)); + expect(result.current).toEqual({ x: 1, y: 1 }); + + act(() => { + removeComponent(Position, entity); + }); + expect(result.current).toBe(undefined); + + act(() => { + setComponent(Position, entity, { x: 0, y: 0 }); + }); + expect(result.current).toEqual({ x: 0, y: 0 }); + }); + it("should return default value when Position is not set", () => { const entity = createEntity(world); diff --git a/packages/react/src/useComponentValue.ts b/packages/react/src/useComponentValue.ts index 63c8beb967..fecb60ede4 100644 --- a/packages/react/src/useComponentValue.ts +++ b/packages/react/src/useComponentValue.ts @@ -33,7 +33,7 @@ export function useComponentValue( setValue(entity != null ? getComponentValue(component, entity) : undefined); if (entity == null) return; - const queryResult = defineQuery([Has(component)], { runOnInit: false }); + const queryResult = defineQuery([Has(component)], { runOnInit: true }); const subscription = queryResult.update$.subscribe((update) => { if (isComponentUpdate(update, component) && update.entity === entity) { const [nextValue] = update.value;