Skip to content

Reactivity System

LiveStore has a high-performance, fine-grained reactivity system built in which is similar to Signals (e.g. in SolidJS).

LiveStore provides 3 types of reactive state:

  • Reactive SQL queries on top of SQLite state (queryDb())
  • Reactive state values (signal())
  • Reactive computed values (computed())

Reactive state variables end on a $ by convention (e.g. todos$). The label option is optional but can be used to identify the reactive state variable in the devtools.

import { queryDb } from '@livestore/livestore'
const todos$ = queryDb(tables.todos.orderBy('createdAt', 'desc'), { label: 'todos$' })
// Or using callback syntax to depend on other queries
const todos$ = queryDb((get) => {
const { showCompleted } = get(uiState$)
return tables.todos.where(showCompleted ? { completed: true } : {})
}, { label: 'todos$' })

Signals are reactive state values that can be set and get. This can be useful for state that is not materialized from events into SQLite tables.

import { signal } from '@livestore/livestore'
const now$ = signal(Date.now(), { label: 'now$' })
setInterval(() => {
store.setSignal(now$, Date.now())
}, 1000)
// Counter example
const num$ = signal(0, { label: 'num$' })
const increment = () => store.setSignal(num$, (prev) => prev + 1)
increment()
increment()
console.log(store.query(num$)) // 2
import { computed } from '@livestore/livestore'
const num$ = signal(0, { label: 'num$' })
const duplicated$ = computed((get) => get(num$) * 2, { label: 'duplicated$' })

Reactive state is always bound to a Store instance. You can access the current value of reactive state the following ways:

// One-off query
const count = store.query(count$)
// By subscribing to the reactive state value
const unsub = count$.subscribe((count) => {
console.log(count)
})
import { useQuery } from '@livestore/react'
const MyComponent = () => {
const value = useQuery(state$)
return <div>{value}</div>
}
import { query } from '@livestore/solid'
const MyComponent = () => {
const value = query(state$)
return <div>{value}</div>
}
  • Signia: Signia is a minimal, fast, and scalable signals library for TypeScript developed by TLDraw.