Custom Adapters
Learn how to create custom adapters to use Zustand Debounce with any storage system.
What is an Adapter?
An adapter is an object that implements the StateStorage
interface and allows Zustand Debounce to work with different storage systems.
interface StateStorage {
getItem: (key: string) => Promise<string | null> | string | null;
setItem: (key: string, value: string) => Promise<void> | void;
removeItem: (key: string) => Promise<void> | void;
}
IndexedDB Adapter
indexeddb-adapter.ts
function createIndexedDBAdapter(dbName: string, storeName: string): StateStorage {
let dbPromise: Promise<IDBDatabase>;
const openDB = () => {
if (!dbPromise) {
dbPromise = new Promise((resolve, reject) => {
const request = indexedDB.open(dbName, 1);
request.onerror = () => reject(request.error);
request.onsuccess = () => resolve(request.result);
request.onupgradeneeded = () => {
const db = request.result;
if (!db.objectStoreNames.contains(storeName)) {
db.createObjectStore(storeName);
}
};
});
}
return dbPromise;
};
return {
async getItem(key: string): Promise<string | null> {
try {
const db = await openDB();
const transaction = db.transaction(storeName, 'readonly');
const store = transaction.objectStore(storeName);
return new Promise((resolve, reject) => {
const request = store.get(key);
request.onsuccess = () => resolve(request.result || null);
request.onerror = () => reject(request.error);
});
} catch (error) {
console.error('Error getting item from IndexedDB:', error);
return null;
}
},
async setItem(key: string, value: string): Promise<void> {
try {
const db = await openDB();
const transaction = db.transaction(storeName, 'readwrite');
const store = transaction.objectStore(storeName);
return new Promise((resolve, reject) => {
const request = store.put(value, key);
request.onsuccess = () => resolve();
request.onerror = () => reject(request.error);
});
} catch (error) {
console.error('Error setting item in IndexedDB:', error);
throw error;
}
},
async removeItem(key: string): Promise<void> {
try {
const db = await openDB();
const transaction = db.transaction(storeName, 'readwrite');
const store = transaction.objectStore(storeName);
return new Promise((resolve, reject) => {
const request = store.delete(key);
request.onsuccess = () => resolve();
request.onerror = () => reject(request.error);
});
} catch (error) {
console.error('Error removing item from IndexedDB:', error);
throw error;
}
},
};
}
// Usage
export const indexedDBStorage = createDebouncedJSONStorage(
createIndexedDBAdapter('MyApp', 'zustand-store'),
{
debounceTime: 1000,
maxRetries: 3,
}
);
Redis Adapter
redis-adapter.ts
import Redis from 'ioredis';
function createRedisAdapter(redisUrl: string): StateStorage {
const redis = new Redis(redisUrl);
return {
async getItem(key: string): Promise<string | null> {
try {
return await redis.get(key);
} catch (error) {
console.error('Error getting item from Redis:', error);
return null;
}
},
async setItem(key: string, value: string): Promise<void> {
try {
await redis.set(key, value);
} catch (error) {
console.error('Error setting item in Redis:', error);
throw error;
}
},
async removeItem(key: string): Promise<void> {
try {
await redis.del(key);
} catch (error) {
console.error('Error removing item from Redis:', error);
throw error;
}
},
};
}
// Usage
export const redisStorage = createDebouncedJSONStorage(
createRedisAdapter('redis://localhost:6379'),
{
debounceTime: 2000,
maxRetries: 5,
retryDelay: 1000,
}
);
React Native Adapter
react-native-adapter.ts
import AsyncStorage from '@react-native-async-storage/async-storage';
const reactNativeAdapter: StateStorage = {
async getItem(key: string): Promise<string | null> {
try {
return await AsyncStorage.getItem(key);
} catch (error) {
console.error('Error getting item from AsyncStorage:', error);
return null;
}
},
async setItem(key: string, value: string): Promise<void> {
try {
await AsyncStorage.setItem(key, value);
} catch (error) {
console.error('Error setting item in AsyncStorage:', error);
throw error;
}
},
async removeItem(key: string): Promise<void> {
try {
await AsyncStorage.removeItem(key);
} catch (error) {
console.error('Error removing item from AsyncStorage:', error);
throw error;
}
},
};
// Usage
export const reactNativeStorage = createDebouncedJSONStorage(
reactNativeAdapter,
{
debounceTime: 500,
maxRetries: 3,
}
);
Next steps
Explore more examples on the examples page or check out advanced configuration.