Skip to content
On this page

Computed Stores

Computed store is based on other store’s value.

import { computed } from 'nanostores'
import { $users } from './users.js'
export const $admins = computed($users, users => {
// This callback will be called on every `users` changes
return users.filter(user => user.isAdmin)
})

Use @nanostores/async for async computed:

import { computedAsync } from '@nanostores/async'
const $org = computedAsync($orgSlug, slug => {
return fetchJson(`/organizations/${slug}`)
})
// The callback receives the resolved org, not an AsyncValue wrapper.
const $profile = computedAsync([$org, $userId], (org, userId) => {
return fetchJson(`/users/${org.id}/${userId}`)
})

By default, computed stores update each time any of their dependencies gets updated. If you are fine with waiting until the end of a tick, you can use batched. The only difference with computed is that it will wait until the end of a tick to update itself.

import { batched } from 'nanostores'
const $sortBy = atom('id')
const $categoryId = atom('')
export const $link = batched([$sortBy, $categoryId], (sortBy, categoryId) => {
return `/api/entities?sortBy=${sortBy}&categoryId=${categoryId}`
})
// `batched` will update only once even you changed two stores
export function resetFilters() {
$sortBy.set('date')
$categoryIdFilter.set('1')
}

Both computed and batched can be calculated from multiple stores:

import { $lastVisit } from './lastVisit.js'
import { $posts } from './posts.js'
export const $newPosts = computed([$lastVisit, $posts], (lastVisit, posts) => {
return posts.filter(post => post.publishedAt > lastVisit)
})

Imported from the Nano Stores README for version 1.5.5. Improve this page there.