Skip to main content

Frequently Asked Questions (FAQ)

Answers to the most common questions about Zustand Debounce.

❓ General Questions​

What is Zustand Debounce?​

Zustand Debounce is an extension for Zustand that optimizes storage write operations through intelligent debouncing. Instead of saving each change immediately, it groups multiple changes and saves them once after a period of inactivity.

Why do I need debounce in my storage?​

Without debounce: If a user makes 10 quick changes, 10 write operations are performed to localStorage/sessionStorage.

With debounce: The same 10 changes are grouped into 1 single write operation.

This results in:

  • 🚀 Better performance
  • 🔋 Less CPU usage
  • 💾 Fewer I/O operations
  • ⚡ Smoother application

Is it compatible with my current project?​

Zustand Debounce is a drop-in replacement for createJSONStorage. You only need:

// Before
storage: createJSONStorage(() => localStorage)

// After
storage: createDebouncedJSONStorage('localStorage', { debounceTime: 1000 })

🔧 Configuration​

What debounceTime value should I use?​

It depends on your use case:

  • 100-500ms: Infrequent changes (settings)
  • 500-1000ms: Forms and user inputs
  • 1000-3000ms: Text editors
  • 3000ms+: Data that changes very frequently (games, animations)

When to use throttleTime vs debounceTime?​

  • debounceTime: Waits until there are no more changes
  • throttleTime: Guarantees a maximum of writes per time
// Only debounce: Wait 1 second after the last change
debounceTime: 1000

// Only throttle: Maximum one write every 5 seconds
throttleTime: 5000

// Both: Wait 1 second, but never more than 5 seconds
debounceTime: 1000,
throttleTime: 5000

When to use immediately: true?​

When you need certain changes to be saved instantly without delay:

// For critical data like authentication
const authStorage = createDebouncedJSONStorage('localStorage', {
immediately: true // Save tokens immediately
});

🔄 Retries​

When to enable retries?​

Enable retries for important data that cannot be lost:

  • ✅ Game progress
  • ✅ Shopping carts
  • ✅ Important forms
  • ❌ Visual preferences (theme, language)
  • ❌ Temporary states

What values to use for retries?​

// Conservative configuration
maxRetries: 3,
retryDelay: 1000

// Aggressive configuration for critical data
maxRetries: 5,
retryDelay: 2000

🚀 Performance​

Does it affect my application's performance?​

Quite the opposite! Zustand Debounce improves performance:

  • ✅ Reduces I/O operations to storage
  • ✅ Prevents main thread blocking
  • ✅ Only 1.74 kB overhead
  • ✅ Zero external dependencies

Does it work with React DevTools?​

Yes, fully compatible. Zustand Debounce doesn't interfere with:

  • React DevTools
  • Zustand DevTools
  • Time-travel debugging
  • Hot reloading

🐛 Troubleshooting​

Changes are not being saved​

Possible causes:

  1. debounceTime too high: Changes are still being "debounced"
  2. Storage error: Check console for errors
  3. Storage full: localStorage has space limits

Solutions:

// Add logging for debug
const storage = createDebouncedJSONStorage('localStorage', {
debounceTime: 1000,
onWrite: (key) => console.log('📝 Writing:', key),
onSave: (key) => console.log('💾 Saved:', key),
onError: (key, error) => console.error('❌ Error:', key, error),
});

Error: "localStorage is not available"​

This occurs in non-browser environments (SSR, Node.js):

// Solution: Detect environment
const storage = createDebouncedJSONStorage(
typeof window !== 'undefined' ? 'localStorage' : 'memoryStorage',
{ debounceTime: 1000 }
);

Retries are not working​

Verify that you have the correct parameters:

const storage = createDebouncedJSONStorage('localStorage', {
maxRetries: 3, // ✅ Required
retryDelay: 1000, // ✅ Required
onRetry: (key, attempt, error, delay) => {
console.log(`Retry ${attempt}: ${error.message}`);
}
});

📱 Compatibility​

Does it work with React Native?​

Yes, but you need a custom adapter:

import AsyncStorage from '@react-native-async-storage/async-storage';

const reactNativeAdapter = {
getItem: async (key: string) => {
return await AsyncStorage.getItem(key);
},
setItem: async (key: string, value: string) => {
await AsyncStorage.setItem(key, value);
},
removeItem: async (key: string) => {
await AsyncStorage.removeItem(key);
},
};

const storage = createDebouncedJSONStorage(reactNativeAdapter, {
debounceTime: 1000
});

Does it work with Next.js?​

Perfectly compatible. For SSR:

const storage = createDebouncedJSONStorage(
typeof window !== 'undefined' ? 'localStorage' : 'memoryStorage',
{ debounceTime: 1000 }
);

Does it work with other frameworks?​

Yes, Zustand Debounce is framework-agnostic. It works with:

  • ✅ React
  • ✅ Vue (with pinia-zustand-adapter)
  • ✅ Angular
  • ✅ Svelte
  • ✅ Vanilla JavaScript

📝 Best Practices​

How to structure multiple stores?​

// Separate by domain
const useUserStore = create(persist(..., {
name: 'user-data',
storage: createDebouncedJSONStorage('localStorage', {
debounceTime: 1000,
maxRetries: 3 // Important data
})
}));

const useUIStore = create(persist(..., {
name: 'ui-preferences',
storage: createDebouncedJSONStorage('localStorage', {
debounceTime: 500 // Fast response for UX
})
}));

How to handle sensitive data?​

const sensitiveStorage = createDebouncedJSONStorage('sessionStorage', {
debounceTime: 0, // No delay for sensitive data
ttl: 30 * 60 * 1000, // Expires in 30 minutes
serialize: (data) => {
// Encrypt before saving
return encrypt(JSON.stringify(data));
},
deserialize: (str) => {
// Decrypt when reading
return JSON.parse(decrypt(str));
}
});

Can't find your question?

If you have a question that's not here, please:

  1. Check the complete documentation
  2. Search GitHub Issues
  3. Open a new issue if you can't find the answer

🤝 Contributing​

Found a bug or have an idea to improve? Contributions are welcome!

  1. Fork the repository
  2. Create a branch for your feature
  3. Send a Pull Request

See more on GitHub →