https://github.com/ts-collection/use-idb-storage
A React hook for IndexedDB state management with automatic persistence, similar to useState but with data persistence across sessions.
https://github.com/ts-collection/use-idb-storage
hooks idb indexeddb npm-package react typescript
Last synced: 5 months ago
JSON representation
A React hook for IndexedDB state management with automatic persistence, similar to useState but with data persistence across sessions.
- Host: GitHub
- URL: https://github.com/ts-collection/use-idb-storage
- Owner: ts-collection
- Created: 2025-12-07T08:07:18.000Z (6 months ago)
- Default Branch: main
- Last Pushed: 2026-01-15T13:54:05.000Z (5 months ago)
- Last Synced: 2026-01-15T17:47:19.821Z (5 months ago)
- Topics: hooks, idb, indexeddb, npm-package, react, typescript
- Language: TypeScript
- Homepage: https://idb-play.vercel.app
- Size: 314 KB
- Stars: 3
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# useIDBStorage
[](https://www.npmjs.com/package/use-idb-storage)
[](https://www.npmjs.com/package/use-idb-storage)


A React hook for IndexedDB state management with automatic persistence, similar to `useState` but with data persistence across sessions.
## Performance
Near-native performance with minimal overhead. Benchmark shows only 1.5ms difference vs `useState` for 400 forced updates:
```json
{
"useState": { "renders": 400, "time": 3317.9 },
"useIDBStorage": { "renders": 400, "time": 3316.4 },
"differenceMs": 1.5
}
```
See [PERFORMANCE.md](./PERFORMANCE.md) for detailed benchmarks.
## Installation
```bash
npm install use-idb-storage
```
## Quick Start
### Basic Usage
```tsx
import { useIDBStorage } from 'use-idb-storage';
function MyComponent() {
const [user, setUser, removeUser] = useIDBStorage({
key: 'current-user',
defaultValue: { name: '', email: '' }
});
return (
setUser({ ...user, name: e.target.value })}
/>
removeUser()}>Clear
Data persists across browser sessions.
);
}
```
### Advanced Usage
Use object destructuring for additional features:
```tsx
function AdvancedComponent() {
const {
data: user,
update: setUser,
reset: clearUser,
loading,
persisted,
error,
lastUpdated,
refresh
} = useIDBStorage({
key: 'current-user',
defaultValue: { name: '', email: '', avatar: null }
});
if (loading) return
Loading...;
if (error) return Error: {error.message};
return (
{user.name || 'Anonymous'}
setUser(prev => ({
...prev,
loginCount: (prev.loginCount || 0) + 1
}))}>
Increment Login Count
setUser({ ...user, name: 'John' })}>
Set Name
Reset
refresh()}>Refresh from DB
Status: {persisted ? 'Saved' : 'Saving...'}
{lastUpdated && (
Last saved: {lastUpdated.toLocaleTimeString()}
)}
);
}
```
### Global Configuration
Configure global defaults that affect all hooks and the exported `idb` instance:
```tsx
import { configureIDBStorage, useIDBStorage, idb } from 'use-idb-storage';
// Set global configuration
configureIDBStorage({
database: 'my-app',
version: 1,
store: 'data'
});
// Hooks automatically use global config
function MyComponent() {
const [user] = useIDBStorage({
key: 'current-user',
defaultValue: { name: '' }
}); // Uses global config: database="my-app", store="data"
// Override specific settings
const [cache] = useIDBStorage({
key: 'api-cache',
defaultValue: {},
store: 'cache' // Overrides global store
}); // Uses: database="my-app", store="cache"
return
...;
}
// The exported instance also uses global config
async function saveGlobalData() {
const store = await idb.store; // Uses global config
await store.set('global-key', 'global-value');
}
```
### Global Configuration (No Context Required)
```tsx
import { configureIDBStorage, idb } from 'use-idb-storage';
// Configure global defaults
configureIDBStorage({
database: 'my-app',
version: 1,
store: 'data'
});
// Use the pre-configured instance
async function saveUser(userData) {
const store = await idb.store;
await store.set('current-user', userData);
}
async function getUser() {
const store = await idb.store;
return await store.get('current-user');
}
```
### Advanced Usage
Use object destructuring for additional features:
```tsx
function AdvancedComponent() {
const {
data: user,
update: setUser,
reset: clearUser,
loading,
persisted,
error,
lastUpdated,
refresh
} = useIDBStorage({
key: 'user-profile',
defaultValue: { name: '', email: '', avatar: null }
});
if (loading) return
Loading...;
if (error) return Error: {error.message};
return (
{user.name || 'Anonymous'}
setUser(prev => ({
...prev,
loginCount: (prev.loginCount || 0) + 1
}))}>
Increment Login Count
setUser({ ...user, name: 'John' })}>
Set Name
Reset
refresh()}>Refresh from DB
Status: {persisted ? 'Saved' : 'Saving...'}
{lastUpdated && (
Last saved: {lastUpdated.toLocaleTimeString()}
)}
);
}
```
### Class-based API
```tsx
import { IDBStorage } from 'use-idb-storage';
const db = new IDBStorage({
database: 'my-app',
version: 1,
store: 'data'
});
const store = await db.get('my-store');
const defaultStore = await db.store;
await store.set('user', { name: 'John', age: 30 });
const user = await store.get('user');
await store.delete('user');
await store.setMany([
['key1', 'value1'],
['key2', 'value2']
]);
const values = await store.getMany(['key1', 'key2']);
await store.update('counter', (val) => (val || 0) + 1);
const allKeys = await store.keys();
await store.clear();
```
## API Reference
### Default Instance
```typescript
import { idb } from 'use-idb-storage';
```
A pre-configured `IDBStorage` instance using global defaults. Perfect for quick usage without setup.
- `idb.store: Promise` - Default store instance
- `idb.get(storeName: string): Promise` - Get a specific store
- `idb.drop(storeName: string): Promise` - Clear a store
- `idb.close(): void` - Close the database connection
#### Global Configuration
Configure global defaults that affect the default `idb` instance:
```typescript
import { configureIDBStorage, idb } from 'use-idb-storage';
// Set global configuration
configureIDBStorage({
database: 'my-app',
version: 1,
store: 'data'
});
// Now idb.store refers to the 'data' store in 'my-app' database
const store = await idb.store;
await store.set('user', { name: 'John' });
```
### IDBStorage Class
Main entry point for database operations.
#### Constructor
```typescript
new IDBStorage(config: IDBConfigValues)
```
#### Properties
- `store: Promise` - Default store instance (convenience getter)
#### Methods
- `get(storeName: string): Promise` - Get a store instance
- `getStore(): Promise` - Get the default store instance
- `drop(storeName: string): Promise` - Clear a store (IndexedDB doesn't support dropping stores after creation)
- `close(): void` - Close the database connection
### IDBStore Class
Provides operations for a specific object store.
#### Methods
**Single Operations:**
- `get(key: string): Promise`
- `set(key: string, value: T): Promise`
- `delete(key: string): Promise`
**Batch Operations:**
- `getMany(keys: string[]): Promise<(T | undefined)[]>`
- `setMany(entries: [string, T][]): Promise`
- `deleteMany(keys: string[]): Promise`
**Utility Operations:**
- `update(key: string, updater: (value: T | undefined) => T): Promise`
- `clear(): Promise`
- `keys(): Promise`
- `values(): Promise`
- `entries(): Promise<[string, T][]>`
### useIDBStorage Hook
Supports both simple `useState`-style usage and advanced object destructuring.
#### Basic Usage
```tsx
const [value, setValue, removeValue] = useIDBStorage({
key: 'my-key',
defaultValue: 'default value'
});
setValue('new value');
setValue(prev => prev + ' updated');
removeValue();
```
#### Advanced Usage
```tsx
const {
data,
update,
reset,
loading,
persisted,
error,
lastUpdated,
refresh
} = useIDBStorage({
key: 'my-key',
defaultValue: 'default value'
});
```
#### Parameters
```typescript
interface IDBStorageOptions {
key: string; // Unique key for the stored value
defaultValue: T; // Default value if none exists in IndexedDB
database?: string; // Database name (uses context default)
version?: number; // Database version (uses context default)
store?: string; // Object store name (uses context default)
}
```
#### Return Types
**Tuple Destructuring** (useState-compatible):
```typescript
[value: T, setValue: (value: T | ((prev: T) => T)) => void, removeValue: () => void]
```
**Object Destructuring** (Full-featured):
```typescript
{
data: T, // The stored data
update: (value: T | ((prev: T) => T)) => void, // Update function
reset: () => void, // Reset to default
loading: boolean, // Loading state
persisted: boolean, // Persistence status
error: Error | null, // Error state
lastUpdated: Date | null, // Last update timestamp
refresh: () => Promise // Force refresh from DB
}
```
### Global Configuration
Configure global defaults for all hooks and the exported `idb` instance:
```typescript
import { configureIDBStorage } from 'use-idb-storage';
configureIDBStorage({
database: 'my-app',
version: 1,
store: 'data'
});
```
This sets the global defaults that are used by:
- All `useIDBStorage` hooks (unless explicitly overridden)
- The exported `idb` instance
### Configuration
```typescript
interface IDBConfigValues {
database: string; // IndexedDB database name
version?: number; // Database version (default: 1)
store: string; // Default object store name
}
// Configure global defaults
configureIDBStorage({
database: 'my-app',
version: 1,
store: 'data'
});
```
## Examples
### User Authentication
```tsx
function AuthProvider({ children }) {
const { data: user, update: setUser, reset: logout, loading } = useIDBStorage({
key: 'auth-user',
defaultValue: null
});
const login = async (credentials) => {
try {
const userData = await api.login(credentials);
setUser(userData);
} catch (error) {
console.error('Login failed:', error);
}
};
if (loading) return
Loading...;
return (
{children}
);
}
```
### Shopping Cart
```tsx
function ShoppingCart() {
const {
data: cart,
update: updateCart,
reset: clearCart,
persisted,
lastUpdated
} = useIDBStorage({
key: 'shopping-cart',
defaultValue: { items: [], total: 0 }
});
const addItem = (item) => {
updateCart(prev => ({
items: [...prev.items, item],
total: prev.total + item.price
}));
};
return (
Cart ({cart.items.length} items)
{cart.items.map(item => (
{item.name} - ${item.price}
))}
Total: ${cart.total}
Clear Cart
Status: {persisted ? 'Saved' : 'Saving...'}
{lastUpdated && • Saved {lastUpdated.toLocaleTimeString()}}
);
}
```
### Auto-Save Form
```tsx
function AutoSaveForm() {
const {
data: formData,
update: updateForm,
loading,
error,
lastUpdated
} = useIDBStorage({
key: 'draft-form',
defaultValue: { title: '', content: '', tags: [] }
});
React.useEffect(() => {
const timer = setTimeout(() => {
console.log('Auto-saved at', new Date().toLocaleTimeString());
}, 1000);
return () => clearTimeout(timer);
}, [formData]);
if (loading) return
Loading draft...;
if (error) return Failed to load draft: {error.message};
return (
updateForm(prev => ({ ...prev, title: e.target.value }))}
placeholder="Title"
/>
updateForm(prev => ({ ...prev, content: e.target.value }))}
placeholder="Content"
/>
{lastUpdated && (
Last saved: {lastUpdated.toLocaleTimeString()}
)}
);
}
```
### Error Handling
```tsx
function RobustComponent() {
const {
data: settings,
update: updateSettings,
reset: resetSettings,
error,
refresh,
loading
} = useIDBStorage({
key: 'user-settings',
defaultValue: { theme: 'light', notifications: true }
});
if (error) {
return (
Failed to load settings: {error.message}
refresh()}>Retry
Reset to Defaults
);
}
if (loading) return
Loading settings...;
return (
Theme:
updateSettings(prev => ({
...prev,
theme: e.target.value
}))}
>
Light
Dark
);
}
```
## Advanced Usage
### Custom Configuration
```tsx
import { configureIDBStorage, useIDBStorage, idb } from 'use-idb-storage';
// Configure global defaults
configureIDBStorage({
database: 'my-app',
version: 2,
store: 'data'
});
function MyComponents() {
// Uses global config: database="my-app", store="data"
const [user] = useIDBStorage({
key: 'user',
defaultValue: { name: '' }
});
// Overrides store: database="my-app", store="cache"
const [cache] = useIDBStorage({
key: 'api-cache',
defaultValue: {},
store: 'cache'
});
// Uses global config: database="my-app", store="data"
const saveToGlobalStore = async () => {
const store = await idb.store;
await store.set('global-key', 'global-value');
};
return
...;
}
```
### Migration
Increment version for schema changes:
```tsx
```
### Class-based API
```tsx
import { IDBStorage } from 'use-idb-storage';
const db = new IDBStorage({ database: 'my-app' });
const store = await db.get('analytics');
await store.setMany([
['pageviews', 1234],
['sessions', 89],
['bounce-rate', 0.45]
]);
const allKeys = await store.keys();
const allData = await store.values();
```
## 🌐 Browser Support
- Chrome 24+
- Firefox 16+
- Safari 10+
- Edge 12+
## 📄 License
ISC