useLocalStorage
Описание
useLocalStorage — хук, который привязывает состояние React к localStorage по заданному ключу.
- Инициализирует значение из хранилища (если там есть валидная строка), иначе — из
initialValue. - Возвращает кортеж
[value, setValue]. setValueпринимает как прямое значение, так и функциональный апдейтер(prev) => next.- Поддерживает настраиваемые
serializer/deserializer, а также синхронизацию между вкладками черезwatch.
Сигнатура
ts
function useLocalStorage<ValueType = undefined>(
key: string,
initialValue?: undefined,
options?: UseLocalStorageOptions<ValueType>,
): UseLocalStorageReturn<ValueType | undefined>;
function useLocalStorage<ValueType>(
key: string,
initialValue: ValueType | (() => ValueType),
options?: UseLocalStorageOptions<ValueType>,
): UseLocalStorageReturn<ValueType>;Параметры
key— ключ вlocalStorage.initialValue?— начальное значение или фабрика. Используется, если в хранилище нет валидной строки.options?— настройки сериализации и поведения:serializer?: (key, value) => string— преобразует значение в строку перед записью.deserializer?: (key, raw) => Value | undefined— парсит строку из хранилища. Вернитеundefined, чтобы считать, что значения нет.watch?: boolean— обновлять ли состояние при изменении этого ключа в других вкладках.
Возвращает:
UseLocalStorageReturn<Value>— кортеж[value, setValue].
Примеры
1) Простейшее сохранение предпочтения
tsx
const [theme, setTheme] = useLocalStorage<'light' | 'dark'>(
'ui:theme',
'light',
);
// позже, при переключении
setTheme('dark');2) Счётчик с функциональным апдейтером
tsx
const [count, setCount] = useLocalStorage<number>('app:count', 0);
const inc = () => setCount((prev) => (prev ?? 0) + 1);
const reset = () => setCount(0);3) Удаление значения (сброс ключа)
tsx
const [token, setToken] = useLocalStorage<string | undefined>('auth:token');
// удалить сохранённое значение и установить state в undefined
setToken(undefined);4) Кастомные сериализаторы
tsx
type Profile = { id: number; name: string };
const serializer = (_key: string, value: Profile) =>
JSON.stringify({ root: value });
const deserializer = (_key: string, rawValue: string): Profile | undefined => {
const parsed = JSON.parse(rawValue);
return parsed?.root;
};
const [profile, setProfile] = useLocalStorage<Profile>(
'user:profile',
{ id: 1, name: 'Ada' },
{ serializer, deserializer },
);5) Синхронизация между вкладками
tsx
const [filter, setFilter] = useLocalStorage<string>('list:filter', '', {
watch: true,
});Поведение
Инициализация
- При маунте читает строку
rawизlocalStorage[key]и применяетdeserializer. - Если
deserializerвернулundefined, используетсяinitialValue.
- При маунте читает строку
Обновление
setValue(next)записывает новую строку (черезserializer) или удаляет ключ, еслиnext === undefined.- Функциональный апдейтер получает текущее значение
prevи должен вернуть следующее.
Смена ключа
- При изменении
keyхук перечитывает значение для нового ключа, снова применяяdeserializer.
- При изменении
Синхронизация между вкладками (если
watch: true)- Обновляет state по событию
storageпри совпаденииkeyиstorageArea.
- Обновляет state по событию
Когда использовать
- Пользовательские настройки (тема, язык, фильтры, раскладки).
- Короткие кэши и флаги (последний открытый таб, «видел ли пользователь баннер»).
- Сохранение форм и черновиков между перезагрузками.
Когда не использовать
- Большие объёмы или сложные структуры (лучше
IndexedDB). - Конфиденциальные данные без шифрования.
- Состояния, которые не нужно переживать перезагрузку.
Частые ошибки
Непоследовательный формат хранения
- При изменении логики сериализации/десериализации старые значения могут не распарситься — планируйте миграции.
Ожидание возврата
initialValueпослеsetValue(undefined)- В текущем маунте
valueстанетundefined.initialValueприменяется только при первом маунте.
- В текущем маунте
Забытый
watchдля общего ключа- Если ключ редактируется из другой вкладки, включайте
watch: true, чтобы получать обновления автоматически.
- Если ключ редактируется из другой вкладки, включайте
Типизация
Экспортируемым типы
UseLocalStorageReturn<Value>—[value: Value, setValue: (action) => void].UseLocalStorageOptions<Value>— опцииserializer/deserializerиwatch.UseLocalStorageSetAction<Value>—Value | ((prev: Value) => Value).