Wednesday, August 27, 2025
Persistence in Real-World Projects: A Practical Guide
Posted by

Persistence in Real-World Projects: A Practical Guide
Ever wondered how your favorite apps remember your preferences, shopping cart items, or form data even after you close the browser? That's persistence in action! Today, we'll explore how QuantaJS makes this magic happen with real-world examples you can actually try.
What is Persistence?
Persistence is the ability to save and restore your application's state automatically. Think of it like a smart memory system that remembers everything important about your app, even when the user refreshes the page or closes the browser.
Real-World Scenarios
Let's look at some everyday situations where persistence makes a huge difference:
1. User Preferences Store
Imagine you're building a productivity app. Users want their theme, language, and notification settings to persist across sessions.
import { createStore, LocalStorageAdapter } from '@quantajs/core';
const userPreferencesStore = createStore('user-preferences', {
state: () => ({
theme: 'light',
language: 'en',
notifications: true,
fontSize: 'medium'
}),
actions: {
updateTheme(theme) {
this.theme = theme;
},
updateLanguage(lang) {
this.language = lang;
},
toggleNotifications() {
this.notifications = !this.notifications;
}
},
persist: {
adapter: new LocalStorageAdapter('user-preferences'),
debounceMs: 300
}
});
Try it yourself: Change the theme below and refresh the page!
2. Shopping Cart Persistence
E-commerce apps need to remember what users have in their cart, even if they accidentally close the browser.
const shoppingCartStore = createStore('shopping-cart', {
state: () => ({
items: [],
total: 0
}),
getters: {
itemCount: (state) => state.items.length,
isEmpty: (state) => state.items.length === 0
},
actions: {
addItem(product) {
const existingItem = this.items.find(item => item.id === product.id);
if (existingItem) {
existingItem.quantity += 1;
} else {
this.items.push({ ...product, quantity: 1 });
}
this.updateTotal();
},
removeItem(productId) {
this.items = this.items.filter(item => item.id !== productId);
this.updateTotal();
},
updateQuantity(productId, quantity) {
const item = this.items.find(item => item.id === productId);
if (item) {
item.quantity = Math.max(0, quantity);
if (item.quantity === 0) {
this.removeItem(productId);
} else {
this.updateTotal();
}
}
},
updateTotal() {
this.total = this.items.reduce((sum, item) => sum + (item.price * item.quantity), 0);
},
clearCart() {
this.items = [];
this.total = 0;
}
},
persist: {
adapter: new LocalStorageAdapter('shopping-cart'),
debounceMs: 500,
include: ['items', 'total']
}
});
Try it yourself: Add items to your cart and refresh the page!
3. Multi-Step Form Persistence
Complex forms with multiple steps can be frustrating if users lose their progress.
const formStore = createStore('contact-form', {
state: () => ({
name: '',
email: '',
message: '',
step: 1
}),
actions: {
updateField(field, value) {
this[field] = value;
},
nextStep() {
if (this.step < 3) this.step++;
},
prevStep() {
if (this.step > 1) this.step--;
},
resetForm() {
this.name = '';
this.email = '';
this.message = '';
this.step = 1;
}
},
persist: {
adapter: new LocalStorageAdapter('contact-form'),
debounceMs: 100,
transform: {
out: (data) => {
// Don't save empty fields
const cleanData = {};
Object.entries(data).forEach(([key, value]) => {
if (value !== '' && value !== null && value !== undefined) {
cleanData[key] = value;
}
});
return cleanData;
}
}
}
});
Try it yourself: Fill out the form steps and refresh the page!
4. Application State Persistence
Complex applications need to remember user preferences, filters, and view states.
const appStateStore = createStore('app-state', {
state: () => ({
currentView: 'dashboard',
filters: {
category: 'all',
status: 'active',
dateRange: 'week'
},
pagination: {
page: 1,
pageSize: 10
},
sidebarCollapsed: false
}),
actions: {
setView(view) {
this.currentView = view;
},
updateFilters(newFilters) {
this.filters = { ...this.filters, ...newFilters };
this.pagination.page = 1; // Reset to first page when filters change
},
setPage(page) {
this.pagination.page = page;
},
toggleSidebar() {
this.sidebarCollapsed = !this.sidebarCollapsed;
}
},
persist: {
adapter: new LocalStorageAdapter('app-state'),
debounceMs: 200,
exclude: ['pagination'] // Don't persist pagination for better UX
}
});
Try it yourself: Change the view, filters, or sidebar state and refresh!
5. Cross-Tab Synchronization
Modern apps need to stay in sync across multiple browser tabs.
const crossTabStore = createStore('cross-tab-demo', {
state: () => ({
lastUpdated: new Date().toLocaleTimeString(),
tabCount: 1
}),
actions: {
updateTimestamp() {
this.lastUpdated = new Date().toLocaleTimeString();
this.tabCount++;
}
},
persist: {
adapter: new LocalStorageAdapter('cross-tab-demo'),
debounceMs: 100
}
});
Try it yourself: Open this page in multiple tabs and watch them sync!
Interactive Demos
Now let's see these concepts in action! Below are real, working examples of QuantaJS persistence:
Interactive QuantaJS Persistence Demos
These demos showcase real QuantaJS persistence features. Try them out!
Key Benefits of QuantaJS Persistence
🚀 Performance Optimized
- Debounced Saves: Prevents excessive storage operations
- Selective Persistence: Only save what you need
- Efficient Updates: Minimal re-renders and storage writes
🛡️ Developer Friendly
- Simple API: Just add
persist
to your store configuration - Type Safe: Full TypeScript support
- Flexible: Multiple storage adapters and configuration options
🔄 Production Ready
- Error Handling: Built-in error recovery and validation
- Migration Support: Handle schema changes gracefully
- Cross-Tab Sync: Automatic synchronization across browser tabs
Best Practices
1. Choose the Right Storage Adapter
- LocalStorage: Good for small amounts of data, simple apps
- SessionStorage: Perfect for temporary session data
- IndexedDB: Best for large datasets and complex applications
2. Optimize with Debouncing
persist: {
adapter: new LocalStorageAdapter('my-store'),
debounceMs: 300 // Save after 300ms of inactivity
}
3. Use Selective Persistence
persist: {
include: ['important', 'user', 'settings'], // Only persist these fields
exclude: ['temporary', 'cache', 'pagination'] // Don't persist these
}
4. Transform Data When Needed
persist: {
transform: {
out: (data) => cleanData(data), // Clean before saving
in: (data) => validateData(data) // Validate after loading
}
}
5. Handle Errors Gracefully
persist: {
onError: (error, operation) => {
console.error(`Persistence ${operation} failed:`, error);
// Fallback to default values or show user notification
}
}
Real-World Use Cases
E-commerce Applications
- Shopping cart persistence
- User preferences and filters
- Recently viewed products
- Wishlist management
Productivity Tools
- Form progress and drafts
- User settings and preferences
- Workspace layouts and configurations
- Recent documents and projects
Gaming Applications
- Game progress and achievements
- User preferences and controls
- High scores and statistics
- Custom configurations
Social Media Platforms
- User preferences and privacy settings
- Feed filters and sorting options
- Draft posts and comments
- Notification preferences
Getting Started
Ready to add persistence to your QuantaJS stores? It's as simple as adding a persist
configuration:
import { createStore, LocalStorageAdapter } from '@quantajs/core';
const myStore = createStore('my-store', {
state: () => ({
// Your state here
}),
actions: {
// Your actions here
},
persist: {
adapter: new LocalStorageAdapter('my-store'),
debounceMs: 300
}
});
Conclusion
Persistence is a game-changer for user experience. With QuantaJS, implementing robust persistence is straightforward and performant. The interactive demos above show real-world scenarios where persistence makes a significant difference.
Try out the demos, experiment with different configurations, and see how QuantaJS can transform your application's user experience. Remember, the best persistence strategy is one that's invisible to users but makes their experience seamless and delightful.
Happy coding! 🚀