diff --git a/src/usePersistStorage.ts b/src/usePersistStorage.ts index 11f5e4b..863c693 100644 --- a/src/usePersistStorage.ts +++ b/src/usePersistStorage.ts @@ -44,7 +44,12 @@ const usePersistStorage = ( migrate = defaultOptions.migrate, sensitive = defaultOptions.sensitive }: UsePersistStorageOptions = defaultOptions -): [Value, AsyncSetState, boolean] => { +): [ + Value, + AsyncSetState, + boolean, + () => Promise + ] => { const currentVersion = useRef(version || 0); const [state, setState] = useState(initialValue); const [restored, setRestored] = useState(false); @@ -148,7 +153,15 @@ const usePersistStorage = ( } }; - return [state, asyncSetState, restored]; + const resetState = async () => { + const newValue: Value = + initialValue instanceof Function + ? initialValue() + : initialValue; + await asyncSetState(newValue); + } + + return [state, asyncSetState, restored, resetState]; }; export default usePersistStorage; diff --git a/tests/usePersistStorage.test.ts b/tests/usePersistStorage.test.ts index c4e6798..0b03057 100644 --- a/tests/usePersistStorage.test.ts +++ b/tests/usePersistStorage.test.ts @@ -50,7 +50,6 @@ test("init, setState, version = 10", async () => { }); expect(result.current[0]).toBe("async change callback"); expect(await store.getItem(KEY)).toBe(toStorageValue("async change callback", 10)); - }); test("restore state", async () => { @@ -78,3 +77,63 @@ test("no persist state", async () => { expect(result.current[0]).toBe("change"); expect(await store.getItem(KEY)).toBeNull(); }); + +test("init, set state, reset state (when initialValue is a Value)", async () => { + const initialValue = "my initial value" + const { result } = renderHook(() => + usePersistStorage(KEY, initialValue, { version: 10 }) + ); + + expect(result.current[0]).toBe(initialValue); + expect(typeof result.current[1]).toBe("function"); + expect(result.current[2]).toBe(false); + + await sleep(100); // wait mount && init asyncStorage; + expect(await store.getItem(KEY)).toBe(toStorageValue(initialValue, 10)); + expect(result.current[2]).toBe(true); + + act(async () => { + await result.current[1]("change"); + }); + expect(result.current[0]).toBe("change"); + + await sleep(100); // wait update asyncStorage; + expect(await store.getItem(KEY)).toBe(toStorageValue("change", 10)); + + act(async () => { // reset state + await result.current[3](); + }); + expect(result.current[0]).toBe(initialValue); + await sleep(100); // wait update asyncStorage; + expect(await store.getItem(KEY)).toBe(toStorageValue(initialValue, 10)); +}); + +test("init, set state, reset state (when initialValue is a function)", async () => { + const initialValue = () => "my initial value" + const { result } = renderHook(() => + usePersistStorage(KEY, initialValue, { version: 10 }) + ); + + expect(result.current[0]).toBe(initialValue()); + expect(typeof result.current[1]).toBe("function"); + expect(result.current[2]).toBe(false); + + await sleep(100); // wait mount && init asyncStorage; + expect(await store.getItem(KEY)).toBe(toStorageValue(initialValue(), 10)); + expect(result.current[2]).toBe(true); + + act(async () => { + await result.current[1]("change"); + }); + expect(result.current[0]).toBe("change"); + + await sleep(100); // wait update asyncStorage; + expect(await store.getItem(KEY)).toBe(toStorageValue("change", 10)); + + act(async () => { // reset state + await result.current[3](); + }); + expect(result.current[0]).toBe(initialValue()); + await sleep(100); // wait update asyncStorage; + expect(await store.getItem(KEY)).toBe(toStorageValue(initialValue(), 10)); +}); \ No newline at end of file