Skip to content

useStorage

Works just like useState but with real-time integration with local or session storage. the initial state is taken from the chosen storage API and every time you change the state, this new value is automatically updated in the storage API.

Installation

npx rabbithook@latest add use-storage

Usage

App.tsx
import useStorage, { useLocalStorage, useSessionStorage } from "@/hooks/use-storage";
function Component() {
const [foo, setFoo] = useLocalStorage("foo", "");
/*
This is also valid
const [foo, setFoo] = useStorage("foo", "", localStorage);
*/
const [bar, setBar] = useSessionStorage("bar", "",);
/*
This is also valid
const [bar, setBar] = useStorage("bar", "", sessionStorage);
*/
return (
<>
<p>foo: { foo }</p>
<input value={foo} onChange={event => setFoo(event.target.value)} />
<p>bar: { bar }</p>
<input value={bar} onChange={event => setBar(event.target.value)} />
</>
);
}

Code

use-storage.ts
import { Dispatch, SetStateAction, useState, useEffect, useCallback } from "react";
type IUseStorageReturnType<T> = [T | null, Dispatch<SetStateAction<T | null>>, () => void];
type IStorageType = typeof localStorage | typeof sessionStorage;
function useLocalStorage<T>(key: string, defaultValue: T): IUseStorageReturnType<T> {
return useStorage(key, defaultValue, window.localStorage);
}
function useSessionStorage<T>(key: string, defaultValue: T): IUseStorageReturnType<T> {
return useStorage(key, defaultValue, window.sessionStorage);
}
function useStorage<T>(key: string, defaultValue: T, storageObject: IStorageType): IUseStorageReturnType<T> {
const [value, setValue] = useState<T | null>(() => {
const jsonValue = storageObject.getItem(key);
if (jsonValue != null) return JSON.parse(jsonValue);
if (typeof defaultValue === "function") {
return defaultValue();
}
return defaultValue;
});
useEffect(() => {
if (value === undefined) return storageObject.removeItem(key);
storageObject.setItem(key, JSON.stringify(value));
}, [key, value, storageObject])
const remove = useCallback(() => {
setValue(null);
}, [])
return [value, setValue, remove]
}
export { useLocalStorage, useSessionStorage };
export default useStorage;