Persistence Guide
Nexa provides two approaches to persist reactive state: signal-level persistence (nexa-persistence) and store-level persistence (nexa-state).
Signal-Level Persistence (nexa-persistence)
Use persistSignal to bind an existing signal to a storage key. Changes are saved automatically.
ts
import { signal } from 'nexa-reactivity'
import { persistSignal } from 'nexa-persistence'
const theme = signal('light')
persistSignal(theme, 'user-theme')
// Value is restored from localStorage on init
// Every write to theme.value auto-saves
theme.value = 'dark'Custom Serialization
ts
persistSignal(mySignal, 'cart-items', {
serialize: (value) => JSON.stringify(value),
deserialize: (raw) => JSON.parse(raw),
})Custom Storage Backend
ts
persistSignal(mySignal, 'session-token', {
storage: sessionStorage,
})Error Handling
If the stored data is corrupted or fails to deserialize, persistSignal logs an error and keeps the signal's current value:
ts
// If localStorage has invalid JSON for "my-key",
// the signal keeps its initial value
const data = signal({ items: [] })
persistSignal(data, 'my-key')Store-Level Persistence (nexa-state)
Use persist from nexa-state for simple key-value persistence:
ts
import { persist } from 'nexa-state'
const theme = persist('theme', 'light')
theme.value = 'dark' // auto-saves to localStorageThis creates a new signal that automatically loads from and saves to localStorage. If the stored JSON is corrupted, it falls back to the initial value.
When to Use Which
| Feature | persistSignal | persist |
|---|---|---|
| Wraps existing signal | ✅ | ❌ (creates new) |
| Custom serialization | ✅ | ❌ |
| Custom storage backend | ✅ | ✅ |
| Error handling | Logs + keeps value | Silent fallback |
| Package | nexa-persistence | nexa-state |
Common Patterns
Persisted User Preferences
ts
const preferences = signal({
theme: 'light',
fontSize: 14,
language: 'en',
})
persistSignal(preferences, 'user-prefs')Persisted Cart
ts
const cart = signal<CartItem[]>([])
persistSignal(cart, 'shopping-cart')
const addItem = (item: CartItem) => {
cart.value = [...cart.value, item]
// Automatically saved to localStorage
}