From 1c52b6424ee2c45f7fa118d2270c71f511d93de4 Mon Sep 17 00:00:00 2001 From: oowd Date: Sun, 23 Jul 2023 11:58:57 +0900 Subject: [PATCH] Add lazy initial state --- src/index.ts | 12 +++++++----- test/useLocalStorage.test.tsx | 9 +++++++++ 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/index.ts b/src/index.ts index abc4e16..078de67 100644 --- a/src/index.ts +++ b/src/index.ts @@ -3,6 +3,7 @@ import { useEffect, useMemo, useRef, useState } from "react"; type Serializer = (object: T | undefined) => string; type Parser = (val: string) => T | undefined; type Setter = React.Dispatch>; +type DefaultValue = T | (() => T) type Options = Partial<{ serializer: Serializer; @@ -13,12 +14,12 @@ type Options = Partial<{ function useLocalStorage( key: string, - defaultValue: T, + defaultValue: DefaultValue, options?: Options ): [T, Setter]; function useLocalStorage( key: string, - defaultValue?: T, + defaultValue?: DefaultValue, options?: Options ) { const opts = useMemo(() => { @@ -36,17 +37,18 @@ function useLocalStorage( const rawValueRef = useRef(null); const [value, setValue] = useState(() => { - if (typeof window === "undefined") return defaultValue; + const newValue = defaultValue instanceof Function ? defaultValue() : defaultValue + if (typeof window === "undefined") return newValue; try { rawValueRef.current = window.localStorage.getItem(key); const res: T = rawValueRef.current ? parser(rawValueRef.current) - : defaultValue; + : newValue; return res; } catch (e) { logger(e); - return defaultValue; + return newValue; } }); diff --git a/test/useLocalStorage.test.tsx b/test/useLocalStorage.test.tsx index 6d74889..d81b9b8 100644 --- a/test/useLocalStorage.test.tsx +++ b/test/useLocalStorage.test.tsx @@ -36,6 +36,11 @@ export function TestComponent() { ); } +function WithLazyInitialState({ text }: { text: string }) { + const [data] = useLocalStorage("username", () => text); + return

{data}

; +} + function WithCustomParser() { const [data] = useLocalStorage("username", "John Doe", { parser: (val) => JSON.parse(val) + "kraw", @@ -174,6 +179,10 @@ describe("useLocalStorage", () => { JSON.stringify("foobarbarbarbar") ); }); + it("uses a lazy initial state", () => { + const { container } = render(); + expect(container.querySelector("p")).toHaveTextContent("johndoe85kraw"); + }); it("uses a custom parser", () => { localStorage.setItem("username", JSON.stringify("johndoe85")); const { container } = render();