apps/mantine.dev/src/pages/hooks/use-local-storage.mdx
import { Layout } from '@/layout'; import { MDX_DATA } from '@/mdx';
export default Layout(MDX_DATA.useLocalStorage);
The use-local-storage hook allows you to use a value from localStorage as React state.
The hook works the same way as useState, but also writes the value to localStorage:
import { useLocalStorage } from '@mantine/hooks';
// The hook will read the value from localStorage.getItem('color-scheme')
// If localStorage is not available or the value at a given key does not exist,
// 'dark' will be assigned to the value variable
const [value, setValue] = useLocalStorage({
key: 'color-scheme',
defaultValue: 'dark',
});
// The value is set both to state and localStorage at 'color-scheme'
setValue('light');
// You can also use a callback like in the useState hook to set the value
setValue((current) => (current === 'dark' ? 'light' : 'dark'));
Example of a color scheme toggle button that uses use-local-storage hook
to store current color scheme in the localStorage:
import { MoonStarsIcon, SunIcon } from '@phosphor-icons/react';
import { ActionIcon } from '@mantine/core';
import { useLocalStorage } from '@mantine/hooks';
function ColorSchemeToggle() {
const [colorScheme, setColorScheme] = useLocalStorage<
'light' | 'dark'
>({
key: 'color-scheme',
defaultValue: 'light',
});
const toggleColorScheme = () =>
setColorScheme((current) =>
current === 'dark' ? 'light' : 'dark'
);
return (
<ActionIcon onClick={toggleColorScheme}>
{colorScheme === 'dark' ? <SunIcon /> : <MoonStarsIcon />}
</ActionIcon>
);
}
Use removeValue callback to clean localStorage/sessionStorage.
When value is removed it is reset to defaultValue:
import { useLocalStorage } from '@mantine/hooks';
const [value, setValue, removeValue] = useLocalStorage({
key: 'color-scheme',
defaultValue: 'light',
});
use-local-storage subscribes to storage event.
When state changes in one tab, it automatically updates the value in all other opened browser tabs.
You can test this feature by opening 2 tabs with Mantine docs side by side and changing the color scheme
(button on the top right or ⌘ + J on MacOS and Ctrl + J on Windows and Linux).
By default, the hook will serialize/deserialize data with JSON.stringify/JSON.parse.
If you need to store data in local storage that cannot be serialized with JSON.stringify
– provide your own serialization handlers:
import { useLocalStorage } from '@mantine/hooks';
const [value, setValue] = useLocalStorage({
key: 'color-scheme',
serialize: (value) => {
/* return value serialized to string */
},
deserialize: (localStorageValue) => {
/* parse localStorage string value and return value */
},
});
superjson is compatible with JSON.stringify/JSON.parse but works for Date, Map, Set and BigInt:
import superjson from 'superjson';
import { useLocalStorage } from '@mantine/hooks';
const defaultValue = { name: 'John', age: 25 };
const [value, setValue] = useLocalStorage({
key: 'data',
defaultValue,
serialize: superjson.stringify,
deserialize: (str) =>
str === undefined ? defaultValue : superjson.parse(str),
});
The use-session-storage hook works the same way as use-local-storage hook but uses sessionStorage instead of window.localStorage:
import { useSessionStorage } from '@mantine/hooks';
const [value, setValue] = useSessionStorage({
key: 'session-key',
defaultValue: 'mantine',
});
You can specify value type same as in useState hook:
import { useLocalStorage } from '@mantine/hooks';
const [value, setValue] = useLocalStorage<'dark' | 'light'>({
key: 'color-scheme',
defaultValue: 'light',
});
To read value from storage without using hook, use readLocalStorageValue/readSessionStorageValue functions.
Functions accept the same arguments as use-local-storage/use-session-storage hooks:
import { readLocalStorageValue } from '@mantine/hooks';
const value = readLocalStorageValue({ key: 'color-scheme' });
interface UseStorageOptions<T> {
/** Local storage key */
key: string;
/** Default value that will be set if value is not found in local storage */
defaultValue?: T;
/** If set to true, value will be updated in useEffect after mount. Default value is true. */
getInitialValueInEffect?: boolean;
/** Determines whether the value must be synced between browser tabs, `true` by default */
sync?: boolean;
/** Function to serialize value into a string to be saved in local storage */
serialize?: (value: T) => string;
/** Function to deserialize string value from local storage to value */
deserialize?: (value: string) => T;
}
type UseStorageReturnValue<T> = [
T, // current value
(val: T | ((prevState: T) => T)) => void, // callback to set value in storage
() => void, // callback to remove value from storage
];
function useLocalStorage<T = string>(
options: UseStorageOptions<T>,
): UseStorageReturnValue<T>;
UseStorageOptions and UseStorageReturnValue types are exported from the @mantine/hooks package;
you can import them in your application:
import type { UseStorageOptions, UseStorageReturnValue } from '@mantine/hooks';