seitu
Version:
95 lines (64 loc) • 1.9 kB
Markdown
# createWebStorageValue
Single-key reactive handle for web storage.
## Usage
```ts
import { createWebStorageValue } from 'seitu/web'
import * as z from 'zod'
const count = createWebStorageValue({
type: 'localStorage',
key: 'count',
schema: z.number(),
defaultValue: 0,
})
count.get()
count.set(1)
count.set(v => v + 1)
count.clear()
```
## Options
| Option | Type | Description |
|--------|------|-------------|
| `type` | `'localStorage' \| 'sessionStorage'` | Storage backend |
| `key` | `string` | Storage key |
| `schema` | `StandardSchemaV1` | Validator |
| `defaultValue` | inferred | Fallback value |
| `onValidationError?` | `(props) => void \| value` | Handle invalid data |
## Interface
```ts
interface WebStorageValue<V> extends Subscribable<V>, Readable<V>, Writable<V>, Clearable {}
```
## Common Mistakes
### [HIGH] Accessing storage during SSR without defaults
Wrong:
```ts
if (typeof window !== 'undefined') {
const v = createWebStorageValue({ ... })
}
```
Correct:
```ts
const v = createWebStorageValue({ type: 'localStorage', key: 'x', schema, defaultValue })
```
Primitives return defaultValue when window is undefined — safe at module level.
### [CRITICAL] Missing schema on standalone overload
Wrong:
```ts
createWebStorageValue({ type: 'localStorage', key: 'count' })
```
Correct:
```ts
createWebStorageValue({ type: 'localStorage', key: 'count', schema: z.number(), defaultValue: 0 })
```
Standalone overload requires schema and defaultValue.
### [CRITICAL] Creating new instance per render in React
Wrong:
```ts
useSubscription(createWebStorageValue({ key: 'x', ... }))
```
Correct:
```ts
useSubscription(() => createWebStorageValue({ key: 'x', ... }), { deps: [userId] })
```
Each instance uses a different storage subscription; use module singleton or useSubscription factory with deps.
## Source
`src/web/web-storage-value/index.ts`