Skip to main content

useLocalStorage

A custom hook that subscribes to a specific key in localStorage using useSyncExternalStore (available from React v18) and synchronizes state whenever the subscribed data changes.

If the subscribed key does not exist in localStorage, you can set a default value via initialValue. In server-side rendering (SSR) environments where localStorage is unavailable, initialValue is returned.

setState accepts either a value directly or a function. When using a function, the current state is provided as an argument.

const { state, setState, removeState } = useLocalStorage<number[]>({
key: 'test',
initialValue: [1, 2],
});

setState([1, 2, 3]);
setState(state => [...state, 3]);

Providing initialValue enables more precise type inference.

const { state, setState } = useLocalStorage<number[]>({
key: 'test',
});

state; // number[] | null
setState(state => {
state; // number[] | null
});
const { state, setState } = useLocalStorage<number[]>({
key: 'test',
initialValue: [],
});

state; // number[]
setState(state => {
state; // number[]
});

The visibilityChange option detects browser tab visibility changes and synchronizes state when the tab becomes visible again. This is useful for cross-tab synchronization, since localStorage is shared across tabs unlike sessionStorage.

const { state, setState } = useLocalStorage<number[]>({
key: 'test',
initialValue: [1, 2],
visibilityChange: true,
});

Code

🔗 View source code


Interface

typescript
interface UseLocalStorageWithoutInitialValueProps {
key: string;
visibilityChange?: boolean;
}

interface UseLocalStorageWithInitialValueProps<T> {
key: string;
initialValue: T | (() => T);
visibilityChange?: boolean;
}

type UseLocalStorageProps<T> =
| UseLocalStorageWithoutInitialValueProps
| UseLocalStorageWithInitialValueProps<T>;
typescript
// Function overloading
function useLocalStorage<T>({
key,
initialValue,
}: UseLocalStorageWithInitialValueProps<T>): {
state: T;
setState: Dispatch<SetStateAction<T>>;
removeState: () => void;
};

function useLocalStorage<T = unknown>({
key,
}: UseLocalStorageWithoutInitialValueProps): {
state: T | null;
setState: Dispatch<SetStateAction<T | null>>;
removeState: () => void;
};

Options

NameTypeDefaultDescription
keystring-The key used to store and retrieve data from localStorage
initialValueT | (() => T)-The initial value returned when the key does not exist in localStorage. Can be a function
visibilityChangebooleanfalseWhether to synchronize state when the tab becomes visible

Returns

NameTypeDescription
stateT | nullThe current value stored in localStorage. Falls back to initialValue or null
setStateDispatch<SetStateAction<T | null>>Function to update the value in localStorage
removeState() => voidFunction to remove the value for the given key from localStorage

Usage

typescript
import { useLocalStorage } from '@modern-kit/react';

const Example = () => {
const { state, setState, removeState } = useLocalStorage<string>({
key: 'test',
initialValue: 'default',
});

return (
<div>
<p>Check localStorage in your browser's DevTools!</p>
<p>state: {state}</p>
<button onClick={() => setState('foo')}>
{`Save "foo" to localStorage key "test"`}
</button>
<button onClick={() => setState('bar')}>
{`Save "bar" to localStorage key "test"`}
</button>
<button onClick={() => removeState()}>
{`Remove localStorage key "test"`}
</button>
</div>
);
};

Example

Check localStorage in your browser's DevTools!

state: default