Для работы с IndexedDB через библиотеку Idb-keyval достаточно установить пакет через npm или yarn:
npm install idb-keyval
или
yarn add idb-keyval
После установки можно импортировать основные функции:
import { get, set, del, clear, keys } from 'idb-keyval';
Эти функции обеспечивают удобный асинхронный доступ к хранилищу без необходимости напрямую работать с низкоуровневым API IndexedDB.
В React часто возникает потребность хранить данные локально между сессиями. Idb-keyval можно использовать совместно с кастомными хуками для синхронизации состояния и IndexedDB.
Пример создания кастомного хука useIdbState, который
автоматически сохраняет и извлекает значение из IndexedDB:
import { useState, useEffect } from 'react';
import { get, set } from 'idb-keyval';
function useIdbState(key, initialValue) {
const [state, setState] = useState(initialValue);
const [loading, setLoading] = useState(true);
useEffect(() => {
let mounted = true;
get(key).then(value => {
if (mounted) {
if (value !== undefined) setState(value);
setLoading(false);
}
});
return () => { mounted = false; };
}, [key]);
const updateState = (newValue) => {
setState(newValue);
set(key, newValue);
};
return [state, updateState, loading];
}
Особенности:
loading позволяет контролировать состояние загрузки
данных из IndexedDB.Хук useIdbState удобно использовать для сохранения
состояния форм между сессиями:
function ProfileForm() {
const [name, setName, loading] = useIdbState('profile-name', '');
const [email, setEmail] = useIdbState('profile-email', '');
if (loading) return <p>Загрузка...</p>;
return (
<form>
<input
type="text"
value={name}
onCha nge={(e) => setName(e.target.value)}
placeholder="Имя"
/>
<input
type="email"
value={email}
onCha nge={(e) => setEmail(e.target.value)}
placeholder="Email"
/>
</form>
);
}
Преимущества:
Idb-keyval поддерживает сохранение сложных объектов, массивов и
других структур JavaScript. Для больших данных рекомендуется
использовать методы get, set и
keys:
import { get, set, keys } from 'idb-keyval';
async function addItemToList(item) {
const list = (await get('todo-list')) || [];
list.push(item);
await set('todo-list', list);
}
async function getAllItems() {
return await get('todo-list') || [];
}
Особенности работы с массивами:
set перезаписывает значение полностью.Для управления состоянием можно использовать del и
clear:
import { del, clear } from 'idb-keyval';
// Удаление конкретного ключа
await del('profile-name');
// Очистка всего хранилища
await clear();
Это полезно для реализации функций выхода пользователя или сброса настроек.
Для глобального состояния можно создать провайдер с контекстом:
import React, { createContext, useContext } from 'react';
const TodoContext = createContext();
export function TodoProvider({ children }) {
const [todos, setTodos, loading] = useIdbState('todos', []);
const addTodo = (text) => {
const newTodos = [...todos, { text, id: Date.now() }];
setTodos(newTodos);
};
return (
<TodoContext.Provider value={{ todos, addTodo, loading }}>
{children}
</TodoContext.Provider>
);
}
export const useTodos = () => useContext(TodoContext);
Преимущества такой архитектуры:
useContext.try/catch для
безопасного сохранения:try {
await set('key', value);
} catch (error) {
console.error('Ошибка при сохранении в IndexedDB', error);
}
Idb-keyval можно использовать для кэширования данных, полученных с сервера. Пример:
async function fetchAndCacheData(url, key) {
const cached = await get(key);
if (cached) return cached;
const response = await fetch(url);
const data = await response.json();
await set(key, data);
return data;
}
Преимущества:
try/catch.Такая организация работы с Idb-keyval позволяет создавать устойчивые, производительные приложения на React с минимальным количеством кода для работы с локальным хранилищем.