React integration for LiveStore
While LiveStore is framework agnostic, the @livestore/react package provides a first-class integration with React.
Features
Section titled “Features”- High performance
- Fine-grained reactivity (using LiveStore’s signals-based reactivity system)
- Instant, synchronous query results (without the need for
useEffectandisLoadingchecks) - Transactional state transitions (via
batchUpdates) - Also supports Expo / React Native via
@livestore/adapter-expo
LiveStoreProvider
Section titled “LiveStoreProvider”In order to use LiveStore with React, you need to wrap your application in a LiveStoreProvider.
import { const makeInMemoryAdapter: (options?: InMemoryAdapterOptions) => Adapter
Create a web-only in-memory LiveStore adapter.
- Runs entirely in memory: fast, zero I/O, great for tests, sandboxes, or ephemeral sessions.
- Works across browser execution contexts: Window, WebWorker, SharedWorker, and ServiceWorker.
- DevTools: to inspect this adapter from the browser DevTools, provide a
sharedWorker in options.devtools.
(The shared worker is used to bridge the DevTools UI to the running session.)
- No persistence support: nothing is written to OPFS/IndexedDB/localStorage.
importSnapshot
can bootstrap initial state only; subsequent changes are not persisted anywhere.
makeInMemoryAdapter } from '@livestore/adapter-web'import { const LiveStoreProvider: <TSyncPayloadSchema extends Schema<any> = Schema<JsonValue, JsonValue, never>>({ renderLoading, renderError, renderShutdown, otelOptions, children, schema, storeId, boot, adapter, batchUpdates, disableDevtools, signal, confirmUnsavedChanges, syncPayload, syncPayloadSchema, debug, }: LiveStoreProviderProps<TSyncPayloadSchema> & React.PropsWithChildren) => React.ReactNode
LiveStoreProvider } from '@livestore/react'import type { type FC<P = {}> = React.FunctionComponent<P>
Represents the type of a function component. Can optionally
receive a type argument that represents the props the component
receives.
FC, type ReactNode = string | number | bigint | boolean | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<ReactNode> | React.ReactPortal | Promise<AwaitedReactNode> | null | undefined
Represents all of the things React can render.
Where
ReactElement
only represents JSX, ReactNode represents everything that can be rendered.
ReactNode } from 'react'import { function unstable_batchedUpdates<A, R>(callback: (a: A) => R, a: A): R (+1 overload)
unstable_batchedUpdates as function batchUpdates<A, R>(callback: (a: A) => R, a: A): R (+1 overload)
batchUpdates } from 'react-dom'
import { const schema: FromInputSchema.DeriveSchema<{ events: { readonly todoCreated: EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }, false>; }; state: InternalState;}>
schema } from './schema.ts'
const const adapter: Adapter
adapter = function makeInMemoryAdapter(options?: InMemoryAdapterOptions): Adapter
Create a web-only in-memory LiveStore adapter.
- Runs entirely in memory: fast, zero I/O, great for tests, sandboxes, or ephemeral sessions.
- Works across browser execution contexts: Window, WebWorker, SharedWorker, and ServiceWorker.
- DevTools: to inspect this adapter from the browser DevTools, provide a
sharedWorker in options.devtools.
(The shared worker is used to bridge the DevTools UI to the running session.)
- No persistence support: nothing is written to OPFS/IndexedDB/localStorage.
importSnapshot
can bootstrap initial state only; subsequent changes are not persisted anywhere.
makeInMemoryAdapter()
export const const Root: FC<{ children: ReactNode;}>
Root: type FC<P = {}> = React.FunctionComponent<P>
Represents the type of a function component. Can optionally
receive a type argument that represents the props the component
receives.
FC<{ children: ReactNode
children: type ReactNode = string | number | bigint | boolean | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<ReactNode> | React.ReactPortal | Promise<AwaitedReactNode> | null | undefined
Represents all of the things React can render.
Where
ReactElement
only represents JSX, ReactNode represents everything that can be rendered.
ReactNode }> = ({ children: ReactNode
children }) => ( <const LiveStoreProvider: <TSyncPayloadSchema extends Schema<any> = Schema<JsonValue, JsonValue, never>>({ renderLoading, renderError, renderShutdown, otelOptions, children, schema, storeId, boot, adapter, batchUpdates, disableDevtools, signal, confirmUnsavedChanges, syncPayload, syncPayloadSchema, debug, }: LiveStoreProviderProps<TSyncPayloadSchema> & React.PropsWithChildren) => React.ReactNode
LiveStoreProvider LiveStoreProviderProps<TSyncPayloadSchema extends Schema<any> = Schema<JsonValue, JsonValue, never>>.schema: LiveStoreSchema<DbSchema, EventDefRecord>
schema={const schema: FromInputSchema.DeriveSchema<{ events: { readonly todoCreated: EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }, false>; }; state: InternalState;}>
schema} LiveStoreProviderProps<TSyncPayloadSchema extends Schema<any> = Schema<JsonValue, JsonValue, never>>.adapter: Adapter
adapter={const adapter: Adapter
adapter} LiveStoreProviderProps<Schema<JsonValue, JsonValue, never>>.batchUpdates: (run: () => void) => void
In order for LiveStore to apply multiple events in a single render,
you need to pass the batchUpdates function from either react-dom or react-native.
// With React DOMimport { unstable_batchedUpdates as batchUpdates } from 'react-dom'
// With React Nativeimport { unstable_batchedUpdates as batchUpdates } from 'react-native'
batchUpdates={function batchUpdates<A, R>(callback: (a: A) => R, a: A): R (+1 overload)
batchUpdates}> {children: ReactNode
children} </const LiveStoreProvider: <TSyncPayloadSchema extends Schema<any> = Schema<JsonValue, JsonValue, never>>({ renderLoading, renderError, renderShutdown, otelOptions, children, schema, storeId, boot, adapter, batchUpdates, disableDevtools, signal, confirmUnsavedChanges, syncPayload, syncPayloadSchema, debug, }: LiveStoreProviderProps<TSyncPayloadSchema> & React.PropsWithChildren) => React.ReactNode
LiveStoreProvider>)import { const defineMaterializer: <TEventDef extends State.SQLite.EventDef.AnyWithoutFn>(_eventDef: TEventDef, materializer: State.SQLite.Materializer<TEventDef>) => State.SQLite.Materializer<TEventDef>
defineMaterializer, import Events
Events, const makeSchema: <TInputSchema extends InputSchema>(inputSchema: TInputSchema) => FromInputSchema.DeriveSchema<TInputSchema>
makeSchema, import Schema
Schema, import State
State } from '@livestore/livestore'
export const const tables: { readonly todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; }>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>; readonly uiState: State.SQLite.ClientDocumentTableDef<...>;}
tables = { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; };}>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>
todos: import State
State.import SQLite
SQLite.function table<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; };}, Partial<...>>(args: { ...;} & Partial<...>): State.SQLite.TableDef<...> (+2 overloads)
Creates a SQLite table definition from columns or an Effect Schema.
This function supports two main ways to define a table:
- Using explicit column definitions
- Using an Effect Schema (either the
name property needs to be provided or the schema needs to have a title/identifier)
// Using explicit columnsconst usersTable = State.SQLite.table({ name: 'users', columns: { id: State.SQLite.text({ primaryKey: true }), name: State.SQLite.text({ nullable: false }), email: State.SQLite.text({ nullable: false }), age: State.SQLite.integer({ nullable: true }), },})
// Using Effect Schema with annotationsimport { Schema } from '@livestore/utils/effect'
const UserSchema = Schema.Struct({ id: Schema.Int.pipe(State.SQLite.withPrimaryKey).pipe(State.SQLite.withAutoIncrement), email: Schema.String.pipe(State.SQLite.withUnique), name: Schema.String, active: Schema.Boolean.pipe(State.SQLite.withDefault(true)), createdAt: Schema.optional(Schema.Date),})
// Option 1: With explicit nameconst usersTable = State.SQLite.table({ name: 'users', schema: UserSchema,})
// Option 2: With name from schema annotation (title or identifier)const AnnotatedUserSchema = UserSchema.annotations({ title: 'users' })const usersTable2 = State.SQLite.table({ schema: AnnotatedUserSchema,})
// Adding indexesconst PostSchema = Schema.Struct({ id: Schema.String.pipe(State.SQLite.withPrimaryKey), title: Schema.String, authorId: Schema.String, createdAt: Schema.Date,}).annotations({ identifier: 'posts' })
const postsTable = State.SQLite.table({ schema: PostSchema, indexes: [ { name: 'idx_posts_author', columns: ['authorId'] }, { name: 'idx_posts_created', columns: ['createdAt'], isUnique: false }, ],})
table({ name: "todos"
name: 'todos', columns: { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; };}
columns: { id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false;}
id: import State
State.import SQLite
SQLite.const text: <string, string, false, typeof NoDefault, true, false>(args: { schema?: Schema.Schema<string, string, never>; default?: typeof NoDefault; nullable?: false; primaryKey?: true; autoIncrement?: false;}) => { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false;} (+1 overload)
text({ primaryKey?: true
primaryKey: true }), text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false;}
text: import State
State.import SQLite
SQLite.const text: () => { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false;} (+1 overload)
text(), completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false;}
completed: import State
State.import SQLite
SQLite.const boolean: <boolean, false, false, false, false>(args: { default?: false; nullable?: false; primaryKey?: false; autoIncrement?: false;}) => { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false;} (+1 overload)
boolean({ default?: false
default: false }), }, }), uiState: State.SQLite.ClientDocumentTableDef<"UiState", { readonly text: string;}, { readonly text: string;}, { partialSet: true; default: { id: undefined; value: { readonly text: ""; }; };}>
uiState: import State
State.import SQLite
SQLite.clientDocument<"UiState", { readonly text: string;}, { readonly text: string;}, { readonly name: "UiState"; readonly schema: Schema.Struct<{ text: typeof Schema.String; }>; readonly default: { readonly value: { readonly text: ""; }; };}>({ name, schema: valueSchema, ...inputOptions }: { name: "UiState"; schema: Schema.Schema<{ readonly text: string; }, { readonly text: string; }, never>;} & { readonly name: "UiState"; readonly schema: Schema.Struct<{ text: typeof Schema.String; }>; readonly default: { readonly value: { readonly text: ""; }; };}): State.SQLite.ClientDocumentTableDef<"UiState", { readonly text: string;}, { readonly text: string;}, { ...;}>export clientDocument
Special:
- Synced across client sessions (e.g. tabs) but not across different clients
- Derived setters
- Emits client-only events
- Has implicit setter-materializers
- Similar to
React.useState (except it's persisted)
Careful:
- When changing the table definitions in a non-backwards compatible way, the state might be lost without
explicit materializers to handle the old auto-generated events
Usage:
// Querying data// `'some-id'` can be ommited for SessionIdSymbolstore.queryDb(clientDocumentTable.get('some-id'))
// Setting data// Again, `'some-id'` can be ommited for SessionIdSymbolstore.commit(clientDocumentTable.set({ someField: 'some-value' }, 'some-id'))
clientDocument({ name: "UiState"
name: 'UiState', schema: Schema.Schema<{ readonly text: string;}, { readonly text: string;}, never> & Schema.Struct<{ text: typeof Schema.String;}>
schema: import Schema
Schema.function Struct<{ text: typeof Schema.String;}>(fields: { text: typeof Schema.String;}): Schema.Struct<{ text: typeof Schema.String;}> (+1 overload)
Struct({ text: typeof Schema.String
text: import Schema
Schema.class Stringexport String
String }), default: { readonly value: { readonly text: ""; };}
default: { value: { readonly text: "";}
value: { text: ""
text: '' } }, }),} as type const = { readonly todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; }>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>; readonly uiState: State.SQLite.ClientDocumentTableDef<...>;}
const
export const const events: { readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>;}
events = { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string;}, { readonly text: string; readonly id: string;}, false>
todoCreated: import Events
Events.synced<"v1.TodoCreated", { readonly text: string; readonly id: string;}, { readonly text: string; readonly id: string;}>(args: { name: "v1.TodoCreated"; schema: Schema.Schema<{ readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, never>;} & Omit<State.SQLite.DefineEventOptions<{ readonly text: string; readonly id: string;}, false>, "derived" | "clientOnly">): State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string;}, { readonly text: string; readonly id: string;}, false>export synced
synced({ name: "v1.TodoCreated"
name: 'v1.TodoCreated', schema: Schema.Schema<{ readonly text: string; readonly id: string;}, { readonly text: string; readonly id: string;}, never>
schema: import Schema
Schema.function Struct<{ id: typeof Schema.String; text: typeof Schema.String;}>(fields: { id: typeof Schema.String; text: typeof Schema.String;}): Schema.Struct<{ id: typeof Schema.String; text: typeof Schema.String;}> (+1 overload)
Struct({ id: typeof Schema.String
id: import Schema
Schema.class Stringexport String
String, text: typeof Schema.String
text: import Schema
Schema.class Stringexport String
String }), }),} as type const = { readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>;}
const
const const materializers: { "v1.TodoCreated": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>>;}
materializers = import State
State.import SQLite
SQLite.const materializers: <{ readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>;}>(_eventDefRecord: { readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>;}, handlers: { "v1.TodoCreated": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>>;}) => { "v1.TodoCreated": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>>;}
materializers(const events: { readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>;}
events, { [const events: { readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>;}
events.todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string;}, { readonly text: string; readonly id: string;}, false>
todoCreated.name: "v1.TodoCreated"
name]: defineMaterializer<State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string;}, { readonly text: string; readonly id: string;}, false>>(_eventDef: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string;}, { readonly text: string; readonly id: string;}, false>, materializer: State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string;}, { readonly text: string; readonly id: string;}, false>>): State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string;}, { readonly text: string; readonly id: string;}, false>>
defineMaterializer(const events: { readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>;}
events.todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string;}, { readonly text: string; readonly id: string;}, false>
todoCreated, ({ id: string
id, text: string
text }) => const tables: { readonly todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; }>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>; readonly uiState: State.SQLite.ClientDocumentTableDef<...>;}
tables.todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; };}>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>
todos.insert: (values: { readonly text: string; readonly id: string; readonly completed?: boolean;}) => QueryBuilder<readonly { readonly id: string; readonly text: string; readonly completed: boolean;}[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; ... 4 more ...; autoIncrement: false; };}>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Insert a new row into the table
Example:
db.todos.insert({ id: '123', text: 'Buy milk', status: 'active' })
insert({ id: string
id, text: string
text, completed?: boolean
completed: false }), ),})
const const state: InternalState
state = import State
State.import SQLite
SQLite.const makeState: <{ tables: { readonly todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; }>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>; readonly uiState: State.SQLite.ClientDocumentTableDef<...>; }; materializers: { ...; };}>(inputSchema: { tables: { readonly todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; }>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>; readonly uiState: State.SQLite.ClientDocumentTableDef<...>; }; materializers: { ...; };}) => InternalState
makeState({ tables: { readonly todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; }>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>; readonly uiState: State.SQLite.ClientDocumentTableDef<...>;}
tables, materializers: { "v1.TodoCreated": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>>;}
materializers })
export const const schema: FromInputSchema.DeriveSchema<{ events: { readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>; }; state: InternalState;}>
schema = makeSchema<{ events: { readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>; }; state: InternalState;}>(inputSchema: { events: { readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>; }; state: InternalState;}): FromInputSchema.DeriveSchema<{ events: { readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>; }; state: InternalState;}>
makeSchema({ events: { readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>;}
events, state: InternalState
state })For scenarios where you have an existing store instance, you can manually create a LiveStoreContext.Provider:
import type { class Store<TSchema extends LiveStoreSchema = LiveStoreSchema.Any, TContext = {}>
Store } from '@livestore/livestore'import { const LiveStoreContext: React.Context<{ stage: "running"; store: LiveStoreContextRunning["store"] & ReactApi;} | undefined>
LiveStoreContext, type type ReactApi = { useQuery: typeof useQuery; useClientDocument: typeof useClientDocument;}
ReactApi } from '@livestore/react'import type { type FC<P = {}> = React.FunctionComponent<P>
Represents the type of a function component. Can optionally
receive a type argument that represents the props the component
receives.
FC, type ReactNode = string | number | bigint | boolean | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<ReactNode> | React.ReactPortal | Promise<AwaitedReactNode> | null | undefined
Represents all of the things React can render.
Where
ReactElement
only represents JSX, ReactNode represents everything that can be rendered.
ReactNode } from 'react'
declare const const store: Store<LiveStoreSchema.Any, {}> & ReactApi
store: class Store<TSchema extends LiveStoreSchema = LiveStoreSchema.Any, TContext = {}>
Store & type ReactApi = { useQuery: typeof useQuery; useClientDocument: typeof useClientDocument;}
ReactApi
export const const Root: FC<{ children: ReactNode;}>
Root: type FC<P = {}> = React.FunctionComponent<P>
Represents the type of a function component. Can optionally
receive a type argument that represents the props the component
receives.
FC<{ children: ReactNode
children: type ReactNode = string | number | bigint | boolean | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<ReactNode> | React.ReactPortal | Promise<AwaitedReactNode> | null | undefined
Represents all of the things React can render.
Where
ReactElement
only represents JSX, ReactNode represents everything that can be rendered.
ReactNode }> = ({ children: ReactNode
children }) => ( <const LiveStoreContext: React.Context<{ stage: "running"; store: LiveStoreContextRunning["store"] & ReactApi;} | undefined>
LiveStoreContext.React.Context<{ stage: "running"; store: LiveStoreContextRunning["store"] & ReactApi; } | undefined>.Provider: React.Provider<{ stage: "running"; store: LiveStoreContextRunning["store"] & ReactApi;} | undefined>
Provider React.ProviderProps<{ stage: "running"; store: LiveStoreContextRunning["store"] & ReactApi; } | undefined>.value: { stage: "running"; store: LiveStoreContextRunning["store"] & ReactApi;} | undefined
value={{ stage: "running"
stage: 'running', store: Store<LiveStoreSchema.Any, {}> & ReactApi
store }}>{children: ReactNode
children}</const LiveStoreContext: React.Context<{ stage: "running"; store: LiveStoreContextRunning["store"] & ReactApi;} | undefined>
LiveStoreContext.React.Context<{ stage: "running"; store: LiveStoreContextRunning["store"] & ReactApi; } | undefined>.Provider: React.Provider<{ stage: "running"; store: LiveStoreContextRunning["store"] & ReactApi;} | undefined>
Provider>)useStore
Section titled “useStore”import { const useStore: (options?: { store?: Store;}) => { store: Store & ReactApi;}
useStore } from '@livestore/react'import type { type FC<P = {}> = React.FunctionComponent<P>
Represents the type of a function component. Can optionally
receive a type argument that represents the props the component
receives.
FC } from 'react'import { function useEffect(effect: React.EffectCallback, deps?: React.DependencyList): void
Accepts a function that contains imperative, possibly effectful code.
useEffect } from 'react'
import { const events: { readonly todoCreated: EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }, false>;}
events } from './schema.ts'
export const const MyComponent: FC
MyComponent: type FC<P = {}> = React.FunctionComponent<P>
Represents the type of a function component. Can optionally
receive a type argument that represents the props the component
receives.
FC = () => { const { const store: Store<LiveStoreSchema.Any, {}> & ReactApi
store } = function useStore(options?: { store?: Store;}): { store: Store & ReactApi;}
useStore()
function useEffect(effect: React.EffectCallback, deps?: React.DependencyList): void
Accepts a function that contains imperative, possibly effectful code.
useEffect(() => { const store: Store<LiveStoreSchema.Any, {}> & ReactApi
store.Store<LiveStoreSchema<TDbSchema extends DbSchema = DbSchema, TEventsDefRecord extends EventDefRecord = EventDefRecord>.Any, {}>.commit: <readonly [{ name: "v1.TodoCreated"; args: { readonly id: string; readonly text: string; };}]>(list_0: { name: "v1.TodoCreated"; args: { readonly id: string; readonly text: string; };}) => void (+3 overloads)
commit(const events: { readonly todoCreated: EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }, false>;}
events.todoCreated: (args: { readonly id: string; readonly text: string;}) => { name: "v1.TodoCreated"; args: { readonly id: string; readonly text: string; };}
Helper function to construct a partial event
todoCreated({ id: string
id: '1', text: string
text: 'Hello, world!' })) }, [const store: Store<LiveStoreSchema.Any, {}> & ReactApi
store])
return <React.JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>
div>...</React.JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>
div>}import { const defineMaterializer: <TEventDef extends State.SQLite.EventDef.AnyWithoutFn>(_eventDef: TEventDef, materializer: State.SQLite.Materializer<TEventDef>) => State.SQLite.Materializer<TEventDef>
defineMaterializer, import Events
Events, const makeSchema: <TInputSchema extends InputSchema>(inputSchema: TInputSchema) => FromInputSchema.DeriveSchema<TInputSchema>
makeSchema, import Schema
Schema, import State
State } from '@livestore/livestore'
export const const tables: { readonly todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; }>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>; readonly uiState: State.SQLite.ClientDocumentTableDef<...>;}
tables = { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; };}>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>
todos: import State
State.import SQLite
SQLite.function table<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; };}, Partial<...>>(args: { ...;} & Partial<...>): State.SQLite.TableDef<...> (+2 overloads)
Creates a SQLite table definition from columns or an Effect Schema.
This function supports two main ways to define a table:
- Using explicit column definitions
- Using an Effect Schema (either the
name property needs to be provided or the schema needs to have a title/identifier)
// Using explicit columnsconst usersTable = State.SQLite.table({ name: 'users', columns: { id: State.SQLite.text({ primaryKey: true }), name: State.SQLite.text({ nullable: false }), email: State.SQLite.text({ nullable: false }), age: State.SQLite.integer({ nullable: true }), },})
// Using Effect Schema with annotationsimport { Schema } from '@livestore/utils/effect'
const UserSchema = Schema.Struct({ id: Schema.Int.pipe(State.SQLite.withPrimaryKey).pipe(State.SQLite.withAutoIncrement), email: Schema.String.pipe(State.SQLite.withUnique), name: Schema.String, active: Schema.Boolean.pipe(State.SQLite.withDefault(true)), createdAt: Schema.optional(Schema.Date),})
// Option 1: With explicit nameconst usersTable = State.SQLite.table({ name: 'users', schema: UserSchema,})
// Option 2: With name from schema annotation (title or identifier)const AnnotatedUserSchema = UserSchema.annotations({ title: 'users' })const usersTable2 = State.SQLite.table({ schema: AnnotatedUserSchema,})
// Adding indexesconst PostSchema = Schema.Struct({ id: Schema.String.pipe(State.SQLite.withPrimaryKey), title: Schema.String, authorId: Schema.String, createdAt: Schema.Date,}).annotations({ identifier: 'posts' })
const postsTable = State.SQLite.table({ schema: PostSchema, indexes: [ { name: 'idx_posts_author', columns: ['authorId'] }, { name: 'idx_posts_created', columns: ['createdAt'], isUnique: false }, ],})
table({ name: "todos"
name: 'todos', columns: { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; };}
columns: { id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false;}
id: import State
State.import SQLite
SQLite.const text: <string, string, false, typeof NoDefault, true, false>(args: { schema?: Schema.Schema<string, string, never>; default?: typeof NoDefault; nullable?: false; primaryKey?: true; autoIncrement?: false;}) => { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false;} (+1 overload)
text({ primaryKey?: true
primaryKey: true }), text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false;}
text: import State
State.import SQLite
SQLite.const text: () => { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false;} (+1 overload)
text(), completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false;}
completed: import State
State.import SQLite
SQLite.const boolean: <boolean, false, false, false, false>(args: { default?: false; nullable?: false; primaryKey?: false; autoIncrement?: false;}) => { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false;} (+1 overload)
boolean({ default?: false
default: false }), }, }), uiState: State.SQLite.ClientDocumentTableDef<"UiState", { readonly text: string;}, { readonly text: string;}, { partialSet: true; default: { id: undefined; value: { readonly text: ""; }; };}>
uiState: import State
State.import SQLite
SQLite.clientDocument<"UiState", { readonly text: string;}, { readonly text: string;}, { readonly name: "UiState"; readonly schema: Schema.Struct<{ text: typeof Schema.String; }>; readonly default: { readonly value: { readonly text: ""; }; };}>({ name, schema: valueSchema, ...inputOptions }: { name: "UiState"; schema: Schema.Schema<{ readonly text: string; }, { readonly text: string; }, never>;} & { readonly name: "UiState"; readonly schema: Schema.Struct<{ text: typeof Schema.String; }>; readonly default: { readonly value: { readonly text: ""; }; };}): State.SQLite.ClientDocumentTableDef<"UiState", { readonly text: string;}, { readonly text: string;}, { ...;}>export clientDocument
Special:
- Synced across client sessions (e.g. tabs) but not across different clients
- Derived setters
- Emits client-only events
- Has implicit setter-materializers
- Similar to
React.useState (except it's persisted)
Careful:
- When changing the table definitions in a non-backwards compatible way, the state might be lost without
explicit materializers to handle the old auto-generated events
Usage:
// Querying data// `'some-id'` can be ommited for SessionIdSymbolstore.queryDb(clientDocumentTable.get('some-id'))
// Setting data// Again, `'some-id'` can be ommited for SessionIdSymbolstore.commit(clientDocumentTable.set({ someField: 'some-value' }, 'some-id'))
clientDocument({ name: "UiState"
name: 'UiState', schema: Schema.Schema<{ readonly text: string;}, { readonly text: string;}, never> & Schema.Struct<{ text: typeof Schema.String;}>
schema: import Schema
Schema.function Struct<{ text: typeof Schema.String;}>(fields: { text: typeof Schema.String;}): Schema.Struct<{ text: typeof Schema.String;}> (+1 overload)
Struct({ text: typeof Schema.String
text: import Schema
Schema.class Stringexport String
String }), default: { readonly value: { readonly text: ""; };}
default: { value: { readonly text: "";}
value: { text: ""
text: '' } }, }),} as type const = { readonly todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; }>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>; readonly uiState: State.SQLite.ClientDocumentTableDef<...>;}
const
export const const events: { readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>;}
events = { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string;}, { readonly text: string; readonly id: string;}, false>
todoCreated: import Events
Events.synced<"v1.TodoCreated", { readonly text: string; readonly id: string;}, { readonly text: string; readonly id: string;}>(args: { name: "v1.TodoCreated"; schema: Schema.Schema<{ readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, never>;} & Omit<State.SQLite.DefineEventOptions<{ readonly text: string; readonly id: string;}, false>, "derived" | "clientOnly">): State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string;}, { readonly text: string; readonly id: string;}, false>export synced
synced({ name: "v1.TodoCreated"
name: 'v1.TodoCreated', schema: Schema.Schema<{ readonly text: string; readonly id: string;}, { readonly text: string; readonly id: string;}, never>
schema: import Schema
Schema.function Struct<{ id: typeof Schema.String; text: typeof Schema.String;}>(fields: { id: typeof Schema.String; text: typeof Schema.String;}): Schema.Struct<{ id: typeof Schema.String; text: typeof Schema.String;}> (+1 overload)
Struct({ id: typeof Schema.String
id: import Schema
Schema.class Stringexport String
String, text: typeof Schema.String
text: import Schema
Schema.class Stringexport String
String }), }),} as type const = { readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>;}
const
const const materializers: { "v1.TodoCreated": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>>;}
materializers = import State
State.import SQLite
SQLite.const materializers: <{ readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>;}>(_eventDefRecord: { readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>;}, handlers: { "v1.TodoCreated": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>>;}) => { "v1.TodoCreated": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>>;}
materializers(const events: { readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>;}
events, { [const events: { readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>;}
events.todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string;}, { readonly text: string; readonly id: string;}, false>
todoCreated.name: "v1.TodoCreated"
name]: defineMaterializer<State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string;}, { readonly text: string; readonly id: string;}, false>>(_eventDef: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string;}, { readonly text: string; readonly id: string;}, false>, materializer: State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string;}, { readonly text: string; readonly id: string;}, false>>): State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string;}, { readonly text: string; readonly id: string;}, false>>
defineMaterializer(const events: { readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>;}
events.todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string;}, { readonly text: string; readonly id: string;}, false>
todoCreated, ({ id: string
id, text: string
text }) => const tables: { readonly todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; }>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>; readonly uiState: State.SQLite.ClientDocumentTableDef<...>;}
tables.todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; };}>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>
todos.insert: (values: { readonly text: string; readonly id: string; readonly completed?: boolean;}) => QueryBuilder<readonly { readonly id: string; readonly text: string; readonly completed: boolean;}[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; ... 4 more ...; autoIncrement: false; };}>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Insert a new row into the table
Example:
db.todos.insert({ id: '123', text: 'Buy milk', status: 'active' })
insert({ id: string
id, text: string
text, completed?: boolean
completed: false }), ),})
const const state: InternalState
state = import State
State.import SQLite
SQLite.const makeState: <{ tables: { readonly todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; }>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>; readonly uiState: State.SQLite.ClientDocumentTableDef<...>; }; materializers: { ...; };}>(inputSchema: { tables: { readonly todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; }>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>; readonly uiState: State.SQLite.ClientDocumentTableDef<...>; }; materializers: { ...; };}) => InternalState
makeState({ tables: { readonly todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; }>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>; readonly uiState: State.SQLite.ClientDocumentTableDef<...>;}
tables, materializers: { "v1.TodoCreated": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>>;}
materializers })
export const const schema: FromInputSchema.DeriveSchema<{ events: { readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>; }; state: InternalState;}>
schema = makeSchema<{ events: { readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>; }; state: InternalState;}>(inputSchema: { events: { readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>; }; state: InternalState;}): FromInputSchema.DeriveSchema<{ events: { readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>; }; state: InternalState;}>
makeSchema({ events: { readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>;}
events, state: InternalState
state })useQuery
Section titled “useQuery”import { const queryDb: { <TResultSchema, TResult = TResultSchema>(queryInput: QueryInputRaw<TResultSchema, ReadonlyArray<any>> | QueryBuilder<TResultSchema, any, any>, options?: { map?: (rows: TResultSchema) => TResult; label?: string; deps?: DepKey; }): LiveQueryDef<TResult>; <TResultSchema, TResult = TResultSchema>(queryInput: ((get: GetAtomResult) => QueryInputRaw<TResultSchema, ReadonlyArray<any>>) | ((get: GetAtomResult) => QueryBuilder<TResultSchema, any, any>), options?: { map?: (rows: TResultSchema) => TResult; label?: string; deps?: DepKey; }): LiveQueryDef<TResult>;}
NOTE queryDb is only supposed to read data. Don't use it to insert/update/delete data but use events instead.
When using contextual data when constructing the query, please make sure to include it in the deps option.
queryDb } from '@livestore/livestore'import { const useStore: (options?: { store?: Store;}) => { store: Store & ReactApi;}
useStore } from '@livestore/react'import type { type FC<P = {}> = React.FunctionComponent<P>
Represents the type of a function component. Can optionally
receive a type argument that represents the props the component
receives.
FC } from 'react'
import { const tables: { readonly todos: TableDef<SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; }>, WithDefaults<...>, Schema<...>>; readonly uiState: ClientDocumentTableDef<...>;}
tables } from './schema.ts'
const const query$: LiveQueryDef<readonly { readonly id: string; readonly text: string; readonly completed: boolean;}[], "def">
query$ = queryDb<readonly { readonly id: string; readonly text: string; readonly completed: boolean;}[], readonly { readonly id: string; readonly text: string; readonly completed: boolean;}[]>(queryInput: QueryInputRaw<readonly { readonly id: string; readonly text: string; readonly completed: boolean;}[], readonly any[]> | QueryBuilder<readonly { readonly id: string; readonly text: string; readonly completed: boolean;}[], any, any>, options?: { map?: (rows: readonly { readonly id: string; readonly text: string; readonly completed: boolean; }[]) => readonly { readonly id: string; readonly text: string; readonly completed: boolean; }[]; label?: string; deps?: DepKey;} | undefined): LiveQueryDef<...> (+1 overload)
NOTE queryDb is only supposed to read data. Don't use it to insert/update/delete data but use events instead.
When using contextual data when constructing the query, please make sure to include it in the deps option.
queryDb(const tables: { readonly todos: TableDef<SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; }>, WithDefaults<...>, Schema<...>>; readonly uiState: ClientDocumentTableDef<...>;}
tables.todos: TableDef<SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; };}>, WithDefaults<...>, Schema<...>>
todos.where: (params: Partial<{ readonly id: string | { op: QueryBuilder<TResult, TTableDef extends TableDefBase, TWithout extends QueryBuilder.ApiFeature = never>.WhereOps.SingleValue; value: string; } | { op: QueryBuilder.WhereOps.MultiValue; value: readonly string[]; } | undefined; readonly text: string | { op: QueryBuilder.WhereOps.SingleValue; value: string; } | { op: QueryBuilder.WhereOps.MultiValue; value: readonly string[]; } | undefined; readonly completed: boolean | ... 2 more ... | undefined;}>) => QueryBuilder<...> (+2 overloads)
where({ completed?: boolean | { op: QueryBuilder.WhereOps.SingleValue; value: boolean;} | { op: QueryBuilder.WhereOps.MultiValue; value: readonly boolean[];} | undefined
completed: true }).orderBy: <"id">(col: "id", direction: "asc" | "desc") => QueryBuilder<readonly { readonly id: string; readonly text: string; readonly completed: boolean;}[], TableDefBase<SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema<boolean, number, never>; default: Some<...>; nullable: false; primaryKey: false; autoIncrement: false; };}>, WithDefaults<...>>, "select" | ... 2 more ... | "row"> (+1 overload)
orderBy('id', 'desc'), { label?: string
Used for debugging / devtools
label: 'completedTodos',})
export const const CompletedTodos: FC
CompletedTodos: type FC<P = {}> = React.FunctionComponent<P>
Represents the type of a function component. Can optionally
receive a type argument that represents the props the component
receives.
FC = () => { const { const store: Store<LiveStoreSchema.Any, {}> & ReactApi
store } = function useStore(options?: { store?: Store;}): { store: Store & ReactApi;}
useStore() const const todos: readonly { readonly id: string; readonly text: string; readonly completed: boolean;}[]
todos = const store: Store<LiveStoreSchema.Any, {}> & ReactApi
store.useQuery: <LiveQueryDef<readonly { readonly id: string; readonly text: string; readonly completed: boolean;}[], "def">>(queryable: LiveQueryDef<readonly { readonly id: string; readonly text: string; readonly completed: boolean;}[], "def">, options?: { store?: Store;}) => readonly { readonly id: string; readonly text: string; readonly completed: boolean;}[]
Returns the result of a query and subscribes to future updates.
Example:
const App = () => { const todos = useQuery(queryDb(tables.todos.query.where({ complete: true }))) return <div>{todos.map((todo) => <div key={todo.id}>{todo.title}</div>)}</div>}
useQuery(const query$: LiveQueryDef<readonly { readonly id: string; readonly text: string; readonly completed: boolean;}[], "def">
query$)
return ( <React.JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>
div> {const todos: readonly { readonly id: string; readonly text: string; readonly completed: boolean;}[]
todos.ReadonlyArray<{ readonly id: string; readonly text: string; readonly completed: boolean; }>.map<JSX.Element>(callbackfn: (value: { readonly id: string; readonly text: string; readonly completed: boolean;}, index: number, array: readonly { readonly id: string; readonly text: string; readonly completed: boolean;}[]) => JSX.Element, thisArg?: any): JSX.Element[]
Calls a defined callback function on each element of an array, and returns an array that contains the results.
map((todo: { readonly id: string; readonly text: string; readonly completed: boolean;}
todo) => ( <React.JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>
div React.Attributes.key?: React.Key | null | undefined
key={todo: { readonly id: string; readonly text: string; readonly completed: boolean;}
todo.id: string
id}>{todo: { readonly id: string; readonly text: string; readonly completed: boolean;}
todo.text: string
text}</React.JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>
div> ))} </React.JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>
div> )}import { const defineMaterializer: <TEventDef extends State.SQLite.EventDef.AnyWithoutFn>(_eventDef: TEventDef, materializer: State.SQLite.Materializer<TEventDef>) => State.SQLite.Materializer<TEventDef>
defineMaterializer, import Events
Events, const makeSchema: <TInputSchema extends InputSchema>(inputSchema: TInputSchema) => FromInputSchema.DeriveSchema<TInputSchema>
makeSchema, import Schema
Schema, import State
State } from '@livestore/livestore'
export const const tables: { readonly todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; }>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>; readonly uiState: State.SQLite.ClientDocumentTableDef<...>;}
tables = { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; };}>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>
todos: import State
State.import SQLite
SQLite.function table<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; };}, Partial<...>>(args: { ...;} & Partial<...>): State.SQLite.TableDef<...> (+2 overloads)
Creates a SQLite table definition from columns or an Effect Schema.
This function supports two main ways to define a table:
- Using explicit column definitions
- Using an Effect Schema (either the
name property needs to be provided or the schema needs to have a title/identifier)
// Using explicit columnsconst usersTable = State.SQLite.table({ name: 'users', columns: { id: State.SQLite.text({ primaryKey: true }), name: State.SQLite.text({ nullable: false }), email: State.SQLite.text({ nullable: false }), age: State.SQLite.integer({ nullable: true }), },})
// Using Effect Schema with annotationsimport { Schema } from '@livestore/utils/effect'
const UserSchema = Schema.Struct({ id: Schema.Int.pipe(State.SQLite.withPrimaryKey).pipe(State.SQLite.withAutoIncrement), email: Schema.String.pipe(State.SQLite.withUnique), name: Schema.String, active: Schema.Boolean.pipe(State.SQLite.withDefault(true)), createdAt: Schema.optional(Schema.Date),})
// Option 1: With explicit nameconst usersTable = State.SQLite.table({ name: 'users', schema: UserSchema,})
// Option 2: With name from schema annotation (title or identifier)const AnnotatedUserSchema = UserSchema.annotations({ title: 'users' })const usersTable2 = State.SQLite.table({ schema: AnnotatedUserSchema,})
// Adding indexesconst PostSchema = Schema.Struct({ id: Schema.String.pipe(State.SQLite.withPrimaryKey), title: Schema.String, authorId: Schema.String, createdAt: Schema.Date,}).annotations({ identifier: 'posts' })
const postsTable = State.SQLite.table({ schema: PostSchema, indexes: [ { name: 'idx_posts_author', columns: ['authorId'] }, { name: 'idx_posts_created', columns: ['createdAt'], isUnique: false }, ],})
table({ name: "todos"
name: 'todos', columns: { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; };}
columns: { id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false;}
id: import State
State.import SQLite
SQLite.const text: <string, string, false, typeof NoDefault, true, false>(args: { schema?: Schema.Schema<string, string, never>; default?: typeof NoDefault; nullable?: false; primaryKey?: true; autoIncrement?: false;}) => { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false;} (+1 overload)
text({ primaryKey?: true
primaryKey: true }), text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false;}
text: import State
State.import SQLite
SQLite.const text: () => { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false;} (+1 overload)
text(), completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false;}
completed: import State
State.import SQLite
SQLite.const boolean: <boolean, false, false, false, false>(args: { default?: false; nullable?: false; primaryKey?: false; autoIncrement?: false;}) => { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false;} (+1 overload)
boolean({ default?: false
default: false }), }, }), uiState: State.SQLite.ClientDocumentTableDef<"UiState", { readonly text: string;}, { readonly text: string;}, { partialSet: true; default: { id: undefined; value: { readonly text: ""; }; };}>
uiState: import State
State.import SQLite
SQLite.clientDocument<"UiState", { readonly text: string;}, { readonly text: string;}, { readonly name: "UiState"; readonly schema: Schema.Struct<{ text: typeof Schema.String; }>; readonly default: { readonly value: { readonly text: ""; }; };}>({ name, schema: valueSchema, ...inputOptions }: { name: "UiState"; schema: Schema.Schema<{ readonly text: string; }, { readonly text: string; }, never>;} & { readonly name: "UiState"; readonly schema: Schema.Struct<{ text: typeof Schema.String; }>; readonly default: { readonly value: { readonly text: ""; }; };}): State.SQLite.ClientDocumentTableDef<"UiState", { readonly text: string;}, { readonly text: string;}, { ...;}>export clientDocument
Special:
- Synced across client sessions (e.g. tabs) but not across different clients
- Derived setters
- Emits client-only events
- Has implicit setter-materializers
- Similar to
React.useState (except it's persisted)
Careful:
- When changing the table definitions in a non-backwards compatible way, the state might be lost without
explicit materializers to handle the old auto-generated events
Usage:
// Querying data// `'some-id'` can be ommited for SessionIdSymbolstore.queryDb(clientDocumentTable.get('some-id'))
// Setting data// Again, `'some-id'` can be ommited for SessionIdSymbolstore.commit(clientDocumentTable.set({ someField: 'some-value' }, 'some-id'))
clientDocument({ name: "UiState"
name: 'UiState', schema: Schema.Schema<{ readonly text: string;}, { readonly text: string;}, never> & Schema.Struct<{ text: typeof Schema.String;}>
schema: import Schema
Schema.function Struct<{ text: typeof Schema.String;}>(fields: { text: typeof Schema.String;}): Schema.Struct<{ text: typeof Schema.String;}> (+1 overload)
Struct({ text: typeof Schema.String
text: import Schema
Schema.class Stringexport String
String }), default: { readonly value: { readonly text: ""; };}
default: { value: { readonly text: "";}
value: { text: ""
text: '' } }, }),} as type const = { readonly todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; }>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>; readonly uiState: State.SQLite.ClientDocumentTableDef<...>;}
const
export const const events: { readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>;}
events = { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string;}, { readonly text: string; readonly id: string;}, false>
todoCreated: import Events
Events.synced<"v1.TodoCreated", { readonly text: string; readonly id: string;}, { readonly text: string; readonly id: string;}>(args: { name: "v1.TodoCreated"; schema: Schema.Schema<{ readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, never>;} & Omit<State.SQLite.DefineEventOptions<{ readonly text: string; readonly id: string;}, false>, "derived" | "clientOnly">): State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string;}, { readonly text: string; readonly id: string;}, false>export synced
synced({ name: "v1.TodoCreated"
name: 'v1.TodoCreated', schema: Schema.Schema<{ readonly text: string; readonly id: string;}, { readonly text: string; readonly id: string;}, never>
schema: import Schema
Schema.function Struct<{ id: typeof Schema.String; text: typeof Schema.String;}>(fields: { id: typeof Schema.String; text: typeof Schema.String;}): Schema.Struct<{ id: typeof Schema.String; text: typeof Schema.String;}> (+1 overload)
Struct({ id: typeof Schema.String
id: import Schema
Schema.class Stringexport String
String, text: typeof Schema.String
text: import Schema
Schema.class Stringexport String
String }), }),} as type const = { readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>;}
const
const const materializers: { "v1.TodoCreated": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>>;}
materializers = import State
State.import SQLite
SQLite.const materializers: <{ readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>;}>(_eventDefRecord: { readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>;}, handlers: { "v1.TodoCreated": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>>;}) => { "v1.TodoCreated": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>>;}
materializers(const events: { readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>;}
events, { [const events: { readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>;}
events.todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string;}, { readonly text: string; readonly id: string;}, false>
todoCreated.name: "v1.TodoCreated"
name]: defineMaterializer<State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string;}, { readonly text: string; readonly id: string;}, false>>(_eventDef: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string;}, { readonly text: string; readonly id: string;}, false>, materializer: State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string;}, { readonly text: string; readonly id: string;}, false>>): State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string;}, { readonly text: string; readonly id: string;}, false>>
defineMaterializer(const events: { readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>;}
events.todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string;}, { readonly text: string; readonly id: string;}, false>
todoCreated, ({ id: string
id, text: string
text }) => const tables: { readonly todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; }>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>; readonly uiState: State.SQLite.ClientDocumentTableDef<...>;}
tables.todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; };}>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>
todos.insert: (values: { readonly text: string; readonly id: string; readonly completed?: boolean;}) => QueryBuilder<readonly { readonly id: string; readonly text: string; readonly completed: boolean;}[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; ... 4 more ...; autoIncrement: false; };}>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Insert a new row into the table
Example:
db.todos.insert({ id: '123', text: 'Buy milk', status: 'active' })
insert({ id: string
id, text: string
text, completed?: boolean
completed: false }), ),})
const const state: InternalState
state = import State
State.import SQLite
SQLite.const makeState: <{ tables: { readonly todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; }>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>; readonly uiState: State.SQLite.ClientDocumentTableDef<...>; }; materializers: { ...; };}>(inputSchema: { tables: { readonly todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; }>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>; readonly uiState: State.SQLite.ClientDocumentTableDef<...>; }; materializers: { ...; };}) => InternalState
makeState({ tables: { readonly todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; }>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>; readonly uiState: State.SQLite.ClientDocumentTableDef<...>;}
tables, materializers: { "v1.TodoCreated": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>>;}
materializers })
export const const schema: FromInputSchema.DeriveSchema<{ events: { readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>; }; state: InternalState;}>
schema = makeSchema<{ events: { readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>; }; state: InternalState;}>(inputSchema: { events: { readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>; }; state: InternalState;}): FromInputSchema.DeriveSchema<{ events: { readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>; }; state: InternalState;}>
makeSchema({ events: { readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>;}
events, state: InternalState
state })useClientDocument
Section titled “useClientDocument”import { const useStore: (options?: { store?: Store;}) => { store: Store & ReactApi;}
useStore } from '@livestore/react'import type { type FC<P = {}> = React.FunctionComponent<P>
Represents the type of a function component. Can optionally
receive a type argument that represents the props the component
receives.
FC } from 'react'
import { const tables: { readonly todos: TableDef<SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; }>, WithDefaults<...>, Schema<...>>; readonly uiState: ClientDocumentTableDef<...>;}
tables } from './schema.ts'
export const const TodoItem: FC<{ id: string;}>
TodoItem: type FC<P = {}> = React.FunctionComponent<P>
Represents the type of a function component. Can optionally
receive a type argument that represents the props the component
receives.
FC<{ id: string
id: string }> = ({ id: string
id }) => { const { const store: Store<LiveStoreSchema.Any, {}> & ReactApi
store } = function useStore(options?: { store?: Store;}): { store: Store & ReactApi;}
useStore() const [const todo: { readonly text: string;}
todo, const updateTodo: StateSetters<ClientDocumentTableDef<"UiState", { readonly text: string;}, { readonly text: string;}, { partialSet: true; default: { id: undefined; value: { readonly text: ""; }; };}>>
updateTodo] = const store: Store<LiveStoreSchema.Any, {}> & ReactApi
store.useClientDocument: <ClientDocumentTableDef<"UiState", { readonly text: string;}, { readonly text: string;}, { partialSet: true; default: { id: undefined; value: { readonly text: ""; }; };}>>(table: ClientDocumentTableDef<"UiState", { readonly text: string;}, { readonly text: string;}, { partialSet: true; default: { id: undefined; value: { readonly text: ""; }; };}>, id: string | typeof SessionIdSymbol, options?: Partial<RowQuery.GetOrCreateOptions<ClientDocumentTableDef<"UiState", { readonly text: string;}, { readonly text: string;}, { partialSet: true; default: { id: undefined; value: { readonly text: ""; }; };}>>> | undefined) => UseClientDocumentResult<...> (+1 overload)
useClientDocument(const tables: { readonly todos: TableDef<SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; }>, WithDefaults<...>, Schema<...>>; readonly uiState: ClientDocumentTableDef<...>;}
tables.uiState: ClientDocumentTableDef<"UiState", { readonly text: string;}, { readonly text: string;}, { partialSet: true; default: { id: undefined; value: { readonly text: ""; }; };}>
uiState, id: string
id)
return ( <React.JSX.IntrinsicElements.button: React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>
button React.ButtonHTMLAttributes<HTMLButtonElement>.type?: "button" | "submit" | "reset" | undefined
type="button" React.DOMAttributes<HTMLButtonElement>.onClick?: React.MouseEventHandler<HTMLButtonElement> | undefined
onClick={() => const updateTodo: (action: SetStateActionPartial<{ readonly text: string;}>) => void
updateTodo({ text?: string
text: 'Hello, world!' })}> {const todo: { readonly text: string;}
todo.text: string
text} </React.JSX.IntrinsicElements.button: React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>
button> )}import { const defineMaterializer: <TEventDef extends State.SQLite.EventDef.AnyWithoutFn>(_eventDef: TEventDef, materializer: State.SQLite.Materializer<TEventDef>) => State.SQLite.Materializer<TEventDef>
defineMaterializer, import Events
Events, const makeSchema: <TInputSchema extends InputSchema>(inputSchema: TInputSchema) => FromInputSchema.DeriveSchema<TInputSchema>
makeSchema, import Schema
Schema, import State
State } from '@livestore/livestore'
export const const tables: { readonly todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; }>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>; readonly uiState: State.SQLite.ClientDocumentTableDef<...>;}
tables = { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; };}>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>
todos: import State
State.import SQLite
SQLite.function table<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; };}, Partial<...>>(args: { ...;} & Partial<...>): State.SQLite.TableDef<...> (+2 overloads)
Creates a SQLite table definition from columns or an Effect Schema.
This function supports two main ways to define a table:
- Using explicit column definitions
- Using an Effect Schema (either the
name property needs to be provided or the schema needs to have a title/identifier)
// Using explicit columnsconst usersTable = State.SQLite.table({ name: 'users', columns: { id: State.SQLite.text({ primaryKey: true }), name: State.SQLite.text({ nullable: false }), email: State.SQLite.text({ nullable: false }), age: State.SQLite.integer({ nullable: true }), },})
// Using Effect Schema with annotationsimport { Schema } from '@livestore/utils/effect'
const UserSchema = Schema.Struct({ id: Schema.Int.pipe(State.SQLite.withPrimaryKey).pipe(State.SQLite.withAutoIncrement), email: Schema.String.pipe(State.SQLite.withUnique), name: Schema.String, active: Schema.Boolean.pipe(State.SQLite.withDefault(true)), createdAt: Schema.optional(Schema.Date),})
// Option 1: With explicit nameconst usersTable = State.SQLite.table({ name: 'users', schema: UserSchema,})
// Option 2: With name from schema annotation (title or identifier)const AnnotatedUserSchema = UserSchema.annotations({ title: 'users' })const usersTable2 = State.SQLite.table({ schema: AnnotatedUserSchema,})
// Adding indexesconst PostSchema = Schema.Struct({ id: Schema.String.pipe(State.SQLite.withPrimaryKey), title: Schema.String, authorId: Schema.String, createdAt: Schema.Date,}).annotations({ identifier: 'posts' })
const postsTable = State.SQLite.table({ schema: PostSchema, indexes: [ { name: 'idx_posts_author', columns: ['authorId'] }, { name: 'idx_posts_created', columns: ['createdAt'], isUnique: false }, ],})
table({ name: "todos"
name: 'todos', columns: { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; };}
columns: { id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false;}
id: import State
State.import SQLite
SQLite.const text: <string, string, false, typeof NoDefault, true, false>(args: { schema?: Schema.Schema<string, string, never>; default?: typeof NoDefault; nullable?: false; primaryKey?: true; autoIncrement?: false;}) => { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false;} (+1 overload)
text({ primaryKey?: true
primaryKey: true }), text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false;}
text: import State
State.import SQLite
SQLite.const text: () => { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false;} (+1 overload)
text(), completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false;}
completed: import State
State.import SQLite
SQLite.const boolean: <boolean, false, false, false, false>(args: { default?: false; nullable?: false; primaryKey?: false; autoIncrement?: false;}) => { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false;} (+1 overload)
boolean({ default?: false
default: false }), }, }), uiState: State.SQLite.ClientDocumentTableDef<"UiState", { readonly text: string;}, { readonly text: string;}, { partialSet: true; default: { id: undefined; value: { readonly text: ""; }; };}>
uiState: import State
State.import SQLite
SQLite.clientDocument<"UiState", { readonly text: string;}, { readonly text: string;}, { readonly name: "UiState"; readonly schema: Schema.Struct<{ text: typeof Schema.String; }>; readonly default: { readonly value: { readonly text: ""; }; };}>({ name, schema: valueSchema, ...inputOptions }: { name: "UiState"; schema: Schema.Schema<{ readonly text: string; }, { readonly text: string; }, never>;} & { readonly name: "UiState"; readonly schema: Schema.Struct<{ text: typeof Schema.String; }>; readonly default: { readonly value: { readonly text: ""; }; };}): State.SQLite.ClientDocumentTableDef<"UiState", { readonly text: string;}, { readonly text: string;}, { ...;}>export clientDocument
Special:
- Synced across client sessions (e.g. tabs) but not across different clients
- Derived setters
- Emits client-only events
- Has implicit setter-materializers
- Similar to
React.useState (except it's persisted)
Careful:
- When changing the table definitions in a non-backwards compatible way, the state might be lost without
explicit materializers to handle the old auto-generated events
Usage:
// Querying data// `'some-id'` can be ommited for SessionIdSymbolstore.queryDb(clientDocumentTable.get('some-id'))
// Setting data// Again, `'some-id'` can be ommited for SessionIdSymbolstore.commit(clientDocumentTable.set({ someField: 'some-value' }, 'some-id'))
clientDocument({ name: "UiState"
name: 'UiState', schema: Schema.Schema<{ readonly text: string;}, { readonly text: string;}, never> & Schema.Struct<{ text: typeof Schema.String;}>
schema: import Schema
Schema.function Struct<{ text: typeof Schema.String;}>(fields: { text: typeof Schema.String;}): Schema.Struct<{ text: typeof Schema.String;}> (+1 overload)
Struct({ text: typeof Schema.String
text: import Schema
Schema.class Stringexport String
String }), default: { readonly value: { readonly text: ""; };}
default: { value: { readonly text: "";}
value: { text: ""
text: '' } }, }),} as type const = { readonly todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; }>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>; readonly uiState: State.SQLite.ClientDocumentTableDef<...>;}
const
export const const events: { readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>;}
events = { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string;}, { readonly text: string; readonly id: string;}, false>
todoCreated: import Events
Events.synced<"v1.TodoCreated", { readonly text: string; readonly id: string;}, { readonly text: string; readonly id: string;}>(args: { name: "v1.TodoCreated"; schema: Schema.Schema<{ readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, never>;} & Omit<State.SQLite.DefineEventOptions<{ readonly text: string; readonly id: string;}, false>, "derived" | "clientOnly">): State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string;}, { readonly text: string; readonly id: string;}, false>export synced
synced({ name: "v1.TodoCreated"
name: 'v1.TodoCreated', schema: Schema.Schema<{ readonly text: string; readonly id: string;}, { readonly text: string; readonly id: string;}, never>
schema: import Schema
Schema.function Struct<{ id: typeof Schema.String; text: typeof Schema.String;}>(fields: { id: typeof Schema.String; text: typeof Schema.String;}): Schema.Struct<{ id: typeof Schema.String; text: typeof Schema.String;}> (+1 overload)
Struct({ id: typeof Schema.String
id: import Schema
Schema.class Stringexport String
String, text: typeof Schema.String
text: import Schema
Schema.class Stringexport String
String }), }),} as type const = { readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>;}
const
const const materializers: { "v1.TodoCreated": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>>;}
materializers = import State
State.import SQLite
SQLite.const materializers: <{ readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>;}>(_eventDefRecord: { readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>;}, handlers: { "v1.TodoCreated": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>>;}) => { "v1.TodoCreated": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>>;}
materializers(const events: { readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>;}
events, { [const events: { readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>;}
events.todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string;}, { readonly text: string; readonly id: string;}, false>
todoCreated.name: "v1.TodoCreated"
name]: defineMaterializer<State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string;}, { readonly text: string; readonly id: string;}, false>>(_eventDef: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string;}, { readonly text: string; readonly id: string;}, false>, materializer: State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string;}, { readonly text: string; readonly id: string;}, false>>): State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string;}, { readonly text: string; readonly id: string;}, false>>
defineMaterializer(const events: { readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>;}
events.todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string;}, { readonly text: string; readonly id: string;}, false>
todoCreated, ({ id: string
id, text: string
text }) => const tables: { readonly todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; }>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>; readonly uiState: State.SQLite.ClientDocumentTableDef<...>;}
tables.todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; };}>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>
todos.insert: (values: { readonly text: string; readonly id: string; readonly completed?: boolean;}) => QueryBuilder<readonly { readonly id: string; readonly text: string; readonly completed: boolean;}[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; ... 4 more ...; autoIncrement: false; };}>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Insert a new row into the table
Example:
db.todos.insert({ id: '123', text: 'Buy milk', status: 'active' })
insert({ id: string
id, text: string
text, completed?: boolean
completed: false }), ),})
const const state: InternalState
state = import State
State.import SQLite
SQLite.const makeState: <{ tables: { readonly todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; }>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>; readonly uiState: State.SQLite.ClientDocumentTableDef<...>; }; materializers: { ...; };}>(inputSchema: { tables: { readonly todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; }>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>; readonly uiState: State.SQLite.ClientDocumentTableDef<...>; }; materializers: { ...; };}) => InternalState
makeState({ tables: { readonly todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; }>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>; readonly uiState: State.SQLite.ClientDocumentTableDef<...>;}
tables, materializers: { "v1.TodoCreated": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>>;}
materializers })
export const const schema: FromInputSchema.DeriveSchema<{ events: { readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>; }; state: InternalState;}>
schema = makeSchema<{ events: { readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>; }; state: InternalState;}>(inputSchema: { events: { readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>; }; state: InternalState;}): FromInputSchema.DeriveSchema<{ events: { readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>; }; state: InternalState;}>
makeSchema({ events: { readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>;}
events, state: InternalState
state })Usage with …
Section titled “Usage with …”LiveStore works with Vite out of the box.
Tanstack Start
Section titled “Tanstack Start”LiveStore works with Tanstack Start out of the box.
Expo / React Native
Section titled “Expo / React Native”LiveStore has a first-class integration with Expo / React Native via @livestore/adapter-expo.
Next.js
Section titled “Next.js”Given various Next.js limitations, LiveStore doesn’t yet work with Next.js out of the box.
Technical notes
Section titled “Technical notes”@livestore/reactusesReact.useStateunder the hood foruseQuery/useClientDocumentto bind LiveStore’s reactivity to React’s reactivity. Some libraries are usingReact.useExternalSyncStorefor similar purposes but usingReact.useStatein this case is more efficient and all that’s needed for LiveStore.@livestore/reactsupports React Strict Mode.