Skip to content

Instantly share code, notes, and snippets.

@podikoglou
Last active March 11, 2025 12:10
Show Gist options
  • Save podikoglou/dbdfa58c8c25f898c403b354eeab37ec to your computer and use it in GitHub Desktop.
Save podikoglou/dbdfa58c8c25f898c403b354eeab37ec to your computer and use it in GitHub Desktop.
LLM-generated Nanostores & Nanostores Persistent Reference

Nano Stores Reference Guide

Nano Stores is a state management library designed for small, fast, and easily tree-shakeable applications. It focuses on moving application logic into stores, making the codebase more modular and testable. It supports multiple frameworks (React, Preact, Vue, Svelte, Solid, Lit, Angular, and vanilla JS).

Nano Stores Persistent (for local storage synchronization): This library extends Nano Stores to manage state persistently in localStorage and synchronize changes across browser tabs.

Core Concepts:

  • Atoms: Basic store for primitive types (e.g., numbers, strings, arrays, objects).
  • Maps: Stores key-value pairs. Changes to keys are tracked and can be used to trigger updates. Handles updating (like setKey()) instead of complete replacement.
  • Deep Maps: Stores objects with nested objects and arrays, maintaining fine-grained reactivity throughout the structure.
  • Computed Stores: Stores calculated from other store values. Evaluates the dependent stores on update without redundant logic. Use computed (standard update on change) or batched (update only once per frame).
  • Tasks: Allows you to wrap asynchronous operations, so subsequent tasks are blocked until the current ones complete. Handles tasks effectively during SSR.
  • Store Lifecycle: Stores have "mount" and "disable" states, ensuring resources are used only when necessary. This manages things like data loading or establishing network connections. onMount() and onStop() are used to manage this.
  • Value Encoding: Allows pre-processing of data when storing values in persistent stores using custom encode, decode functions.

Common Functions (Illustrative):

Atoms (atom)

import { atom } from 'nanostores'

export const $counter = atom(0)
  • $counter.set(value): Sets the value of the counter. Example: $counter.set($counter.get() + 1).
  • $counter.get(): Returns the current value. Example: const currentCount = $counter.get().
  • $counter.subscribe(callback): Subscribes to changes in the store. Example: $counter.subscribe(value => console.log(value)).
  • $counter.listen(callback): listers are called only when the store changes. Example: $counter.listen(value => console.log(value)).

Maps (map)

import { map } from 'nanostores'

export const $profile = map({ name: 'anonymous' })
  • $profile.set(object): Sets the entire object at once. If you have $profile.setKey() then it should be used.
  • $profile.setKey(key, newValue): Sets a specific key's value. Example: $profile.setKey('name', 'Updated Name'). Useful for dynamic object updates.
  • $profile.listen((profile, previousProfile, changedKey) => { /* ... */ }): Listens for both full object and specific updates. Receives the current & old objects and the updated key.

Persistent Stores (Example):

import { persistentAtom } from '@nanostores/persistent'

export const shoppingCart = persistentAtom<Product[]>('cart', [], {
  encode: JSON.stringify,
  decode: JSON.parse,
})
  • Save and sync data in localStorage.
  • Use encode / decode options to support complex value-types like objects or arrays.

Server-Side Rendering (Illustrative):

if (isServer) {
  locale.set(user.locale) // Initialize stores in the server context
}
  • Stores will not use localStorage in server-side environment, but they can be initialized.

Framework Integration (Illustrative):

import { useStore } from '@nanostores/react' // React integration
import { $profile } from './profile.js'

export const Header = () => {
  const profile = useStore($profile)
 return <header>Hi, {profile.name}</header>
}

Other Notes:

  • listenKeys() allows for fine-grained control over which keys trigger updates in map stores.
  • onMount, onStart, onStop, onSet, and onNotify can be used to manage store lifecycle. onMount is generally preferred for handling the lazy load behavior of stores.
  • Testing techniques like useTestStorageEngine are provided to work with mock storage engines.
  • cleanStores and keepMount support lazy stores in testing, ensuring clean tests.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment