From f157c980248df3159c86d065a3ae3949c336da86 Mon Sep 17 00:00:00 2001 From: Konstantin Lukas Date: Thu, 12 Sep 2024 18:02:09 +0200 Subject: [PATCH] move local storage state initialization to useEffect to avoid hydration errors --- package.json | 2 +- src/hooks/useLocalStorage.ts | 22 +++++++++++++--------- tests/useLocalStorage.test.ts | 5 +++++ 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index df26e4b..457d28e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "anzol", - "version": "2.6.0", + "version": "2.6.1", "main": "dist/index.cjs.js", "module": "dist/index.esm.js", "types": "dist/index.d.ts", diff --git a/src/hooks/useLocalStorage.ts b/src/hooks/useLocalStorage.ts index b047d6e..d0f57ab 100644 --- a/src/hooks/useLocalStorage.ts +++ b/src/hooks/useLocalStorage.ts @@ -28,24 +28,28 @@ export interface LocalStorageOptions { * return setValue(e.target.value)} />; * } * ``` -*/ + */ function useLocalStorage(key: string, { initialValue, propagateChanges = false, listenForChanges = false, }: LocalStorageOptions = {}): [string | null, Dispatch>] { - const [value, setValue] = useState(() => { - if (typeof window === "undefined") return null; - const storedValue = localStorage.getItem(key); - if (storedValue) return storedValue; - const init = initialValue || null; - if (init) localStorage.setItem(key, init); - return init; - }); + const [value, setValue] = useState(null); const [blockUpdates, setBlockUpdates] = useState(true); const id = useId(); + useEffect(() => { + if (typeof window === "undefined") return; + setValue(() => { + const storedValue = localStorage.getItem(key); + if (storedValue) return storedValue; + const init = initialValue || null; + if (init) localStorage.setItem(key, init); + return init; + }); + }, [key, initialValue]); + useEffect(() => { if (typeof window === "undefined") return; if (!blockUpdates) { diff --git a/tests/useLocalStorage.test.ts b/tests/useLocalStorage.test.ts index ddc2c62..9bf1115 100644 --- a/tests/useLocalStorage.test.ts +++ b/tests/useLocalStorage.test.ts @@ -23,6 +23,11 @@ async function renderUseLocalStorage({ } describe("useLocalStorage", () => { + + afterEach(() => { + localStorage.clear(); + }); + test("should set a default value when local storage item doesn't exist", async () => { const { result } = await renderUseLocalStorage({ initialKey: "animal", initialOptions: { initialValue: "Bear" }}); expect(result.current[0]).toBe("Bear");