storage()
storage() wraps a default value and makes the variable persistent. It reads
from localStorage when the component mounts, falls back to your default, and saves again on
every assignment.
Nothing else changes: it is still an ordinary reactive let.
<script>
let theme = storage('light')
</script>
<button onclick="theme = theme === 'light' ? 'dark' : 'light'">
Theme is {theme} - click to switch
</button>
<style>
button {
padding: 0.35rem 0.75rem;
border: 1px solid var(--border);
border-radius: var(--radius-sm);
background: var(--bg-secondary);
color: var(--text-primary);
cursor: pointer;
}
</style>Click it, reload the page, and the theme is still the one you chose.
Any Type
Strings, numbers, booleans, objects and arrays are all serialised for you:
<script>
let theme = storage('light') // String
let fontSize = storage(16) // Number
let soundEnabled = storage(true) // Boolean
let user = storage(null) // Null (until set)
let prefs = storage({ dark: false, size: 14 }) // Object
let recentItems = storage([]) // Array
</script>
Keys and sessionStorage
The storage key is the variable's name with a jaf: prefix, so
let theme = storage('light') writes jaf:theme.
Pass a string first to choose your own key, and an options object last to use sessionStorage, which lasts until the tab closes:
let theme = storage('light') // jaf:theme
let theme = storage('ui:theme', 'light') // jaf:ui:theme
let draft = storage('', { storage: 'session' }) // sessionStorage
let draft = storage('form:draft', '', { storage: 'session' })
An object on its own is a default value, not options -
storage({ dark: false }) means what it looks like. Options are only read
from a final argument, and anything JAF cannot make sense of is reported in the console
by variable name rather than dropped in silence.
A Worked Example
A form draft that survives a reload is three characters of difference from one that does not:
<script>
let draft = storage({ title: '', body: '' })
function clearDraft() {
draft = { title: '', body: '' }
}
</script>
<input bind:value={draft.title} placeholder="Title" />
<textarea bind:value={draft.body} placeholder="Type here, then reload the page"></textarea>
<button onclick="clearDraft()">Clear</button>
<style>
input,
textarea {
display: block;
width: 100%;
max-width: 22rem;
margin-bottom: 0.5rem;
}
button {
padding: 0.35rem 0.75rem;
border: 1px solid var(--border);
border-radius: var(--radius-sm);
background: var(--bg-secondary);
color: var(--text-primary);
cursor: pointer;
}
</style>To clear a stored value, assign the default back to it - that is saved like any other assignment.
To wipe everything, use localStorage.clear() and reload.
Outside a Component
The same persistence is available as a plain API for code that is not a component:
import { persistedStore, persisted } from 'jafjs'
// A reactive object, persisted under the key you give it
const settings = persistedStore('app-settings', { theme: 'light', language: 'en' })
settings.theme = 'dark' // saved
// A single value
const counter = persisted('counter', 0)
counter.value++ // saved
// Options, and manual control
persistedStore('session', initialState, { storage: 'session', debounce: 100 })
settings.$persist() // force a save
settings.$clear() // drop the stored copy