From 67a83f9d17c53a6c069147fa9b70d3efa7627070 Mon Sep 17 00:00:00 2001 From: Nate Higgins Date: Mon, 17 Apr 2023 18:39:17 +0100 Subject: [PATCH 1/3] Ensure the identity of set/remove don't change when used --- .../src/__tests__/useLocalstorageState.spec.tsx | 14 ++++++++++++++ packages/rooks/src/hooks/useLocalstorageState.ts | 7 +++++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/packages/rooks/src/__tests__/useLocalstorageState.spec.tsx b/packages/rooks/src/__tests__/useLocalstorageState.spec.tsx index 94373c3e2c..b5f45be7d9 100644 --- a/packages/rooks/src/__tests__/useLocalstorageState.spec.tsx +++ b/packages/rooks/src/__tests__/useLocalstorageState.spec.tsx @@ -68,6 +68,20 @@ describe("useLocalstorageState basic", () => { const removeAfterRerender = result.current[2]; expect(setBeforeRerender).toBe(setAfterRerender); expect(removeBeforeRerender).toBe(removeAfterRerender); + act(() => { + setBeforeRerender("next value"); + }); + const setAfterSet = result.current[1]; + const removeAfterSet = result.current[2]; + expect(setBeforeRerender).toBe(setAfterSet); + expect(removeBeforeRerender).toBe(removeAfterSet); + act(() => { + removeBeforeRerender(); + }); + const setAfterRemove = result.current[1]; + const removeAfterRemove = result.current[2]; + expect(setBeforeRerender).toBe(setAfterRemove); + expect(removeBeforeRerender).toBe(removeAfterRemove); }); it("initializes correctly", () => { diff --git a/packages/rooks/src/hooks/useLocalstorageState.ts b/packages/rooks/src/hooks/useLocalstorageState.ts index d69ac36a00..e1e1be4c0e 100644 --- a/packages/rooks/src/hooks/useLocalstorageState.ts +++ b/packages/rooks/src/hooks/useLocalstorageState.ts @@ -1,3 +1,4 @@ +import { useFreshRef } from "@/hooks/useFreshRef"; import type { Dispatch, SetStateAction } from "react"; import { useMemo, useState, useEffect, useCallback, useRef } from "react"; @@ -174,18 +175,20 @@ function useLocalstorageState( [customEventTypeName] ); + const currentValue = useFreshRef(value, true); + const set = useCallback( (newValue: SetStateAction) => { const resolvedNewValue = typeof newValue === "function" - ? (newValue as (prevState: S) => S)(value) + ? (newValue as (prevState: S) => S)(currentValue.current) : newValue; isUpdateFromCrossDocumentListener.current = false; isUpdateFromWithinDocumentListener.current = false; setValue(resolvedNewValue); broadcastValueWithinDocument(resolvedNewValue); }, - [broadcastValueWithinDocument, value] + [broadcastValueWithinDocument, currentValue] ); const remove = useCallback(() => { From 8d8753b1b7484ffe68935ba1ab00af37e90d54d1 Mon Sep 17 00:00:00 2001 From: Nate Higgins Date: Mon, 17 Apr 2023 18:43:02 +0100 Subject: [PATCH 2/3] Add changeset --- .changeset/stale-poets-walk.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/stale-poets-walk.md diff --git a/.changeset/stale-poets-walk.md b/.changeset/stale-poets-walk.md new file mode 100644 index 0000000000..41afa2a274 --- /dev/null +++ b/.changeset/stale-poets-walk.md @@ -0,0 +1,5 @@ +--- +"rooks": patch +--- + +useLocalstorageState: ensure stable identity for set/remove functions From 327972ed9291b97cbea277bf1e9f7d47ff519ad1 Mon Sep 17 00:00:00 2001 From: Nate Higgins Date: Mon, 17 Apr 2023 18:45:46 +0100 Subject: [PATCH 3/3] Tidier import --- packages/rooks/src/hooks/useLocalstorageState.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/rooks/src/hooks/useLocalstorageState.ts b/packages/rooks/src/hooks/useLocalstorageState.ts index e1e1be4c0e..7f63ddab3e 100644 --- a/packages/rooks/src/hooks/useLocalstorageState.ts +++ b/packages/rooks/src/hooks/useLocalstorageState.ts @@ -1,6 +1,6 @@ -import { useFreshRef } from "@/hooks/useFreshRef"; import type { Dispatch, SetStateAction } from "react"; import { useMemo, useState, useEffect, useCallback, useRef } from "react"; +import { useFreshRef } from "./useFreshRef"; // Gets value from localstorage function getValueFromLocalStorage(key: string) {