-
Notifications
You must be signed in to change notification settings - Fork 0
useIndexedDB
A powerful, high-performance React hook for safely persisting state asynchronously in the browser using IndexedDB. This hook provides the familiar ergonomics of useState, but stores values that outlive browser reloads and easily handles vast amounts of structured data like arrays, blobs, and dates without the blocking performance constraints of localStorage.
Features built-in:
- Global connection pooling: Safely handles opening the database connection exactly once and handles store creation.
-
Familiar API: Uses the tuple
[value, setValue]identical touseStatewith a thirdmetaparameter for IndexedDB state. -
Auto-Sync: Instantly synchronizes your hook state across all open browser tabs using the native
BroadcastChannel. -
Updater Pattern: Supports robust updates via
setValue(prev => [...prev, newItem]). -
Zero serialization: Native IndexedDB structured cloning preserves raw JS objects (no
JSON.stringifyneeded!).
Before calling useIndexedDB anywhere in your component tree, you must initialize the global database connection. The best place to do this is in your app's entry file (e.g. index.tsx, App.tsx, or _app.tsx).
import { createIndexedDB } from 'react-hook-lab';
// Initialize the database once
createIndexedDB({
dbName: 'my-app-database',
version: 1, // Bump this if you add new stores in the future
stores: ['settings', 'cache', 'users']
});import { useIndexedDB } from 'react-hook-lab';
function SettingsPanel() {
const [theme, setTheme, { status }] = useIndexedDB('settings', 'theme-pref', 'light');
// IndexedDB is asynchronous!
if (status === 'loading') {
return <p>Loading preferences...</p>;
}
return (
<div>
<p>Current theme: {theme}</p>
<button onClick={() => setTheme('dark')}>Dark Mode</button>
<button onClick={() => setTheme('light')}>Light Mode</button>
</div>
);
}Just like React's useState, you can pass a function to update the value based on its previous state.
const [history, setHistory] = useIndexedDB('cache', 'search-history', []);
// Add item without needing a stale reference to `history`
const addSearch = (term) => {
setHistory((prev) => [...prev, term]);
};Use the meta.remove() method to erase the key entirely from the database and revert the local state back to the fallback initialValue.
const [user, setUser, { remove, status }] = useIndexedDB('users', 'active-profile', null);
const handleLogout = async () => {
await remove();
// user is now instantly `null`, and the DB record is deleted
};If IndexedDB is blocked by privacy settings or disk quota limits, meta.status will transition to "error".
const [data, setData, { status, error }] = useIndexedDB('cache', 'api-results', []);
if (status === 'error') {
console.error("IndexedDB Error:", error.message);
}Because useIndexedDB leverages BroadcastChannel under the hood, it automatically syncs state across multiple browser tabs!
If a user changes their theme to "dark" in Tab A:
-
setValue('dark')writes to IndexedDB. - A broadcast message is fired.
- Tab B instantly detects the broadcast and updates its local
themestate to"dark".
You do not need to configure anything to enable this behavior; it works securely out of the box!
Built with ❤️ by Saurav-TB-Pandey. | Report an Issue | NPM