lily/store

The Store holds your application state and update logic. It’s the core of Lily’s reactive system, used by both client and server.

The store manages your model (immutable application state), the update function (how messages transform the model), and handlers (functions that run when the model changes, keyed by CSS selector). It’s pure Gleam with no target-specific code - the same store runs on the client via client.start and the server via server.start, meaning your update function works identically on both sides.

import lily/store

pub type Model {
  Model(count: Int, user: String)
}

pub type Message {
  Increment
  Decrement
  SetUser(String)
}

pub fn update(model: Model, message: Message) -> Model {
  case message {
    Increment -> Model(..model, count: model.count + 1)
    Decrement -> Model(..model, count: model.count - 1)
    SetUser(name) -> Model(..model, user: name)
  }
}

pub fn main() {
  let app_store = store.new(Model(count: 0, user: "Guest"), with: update)
  // Pass to client.start() or server.start()
}

Components subscribe to the store via store.subscribe using CSS selector strings as keys. If a new component uses the same selector, it replaces the previous handler.

Types

The store with the model of your application state, update logic, and handlers that are attached to each component that is subscribed to the model. These handlers are keyed by a selector using CSS selector strings.

pub type Store(model, message) {
  Store(
    model: model,
    update: fn(model, message) -> model,
    handlers: dict.Dict(String, fn(model) -> Nil),
  )
}

Constructors

  • Store(
      model: model,
      update: fn(model, message) -> model,
      handlers: dict.Dict(String, fn(model) -> Nil),
    )

Values

pub fn new(
  initial_model model: model,
  with update: fn(model, message) -> model,
) -> Store(model, message)

Create a new store, seeded with an initial_model and an update function that can update a model based on a given message. See Lustre documentation for an explanation on the Model / Message format, although note that the runtime and rendering are owned by components within Lily.

pub fn subscribe(
  store: Store(model, message),
  selector selector: String,
  with handler: fn(model) -> Nil,
) -> Store(model, message)

Allows a (frontend) component to subscribe to a specific store. Handlers are the functions that each component runs on receiving the updated model. If a handler is already registered for the given selector, it will be replaced. No cleanup is performed on override – for most use cases, use functions within the component module.

pub fn unsubscribe(
  store: Store(model, message),
  selector: String,
) -> Store(model, message)

Removes a handler for the given selector, effectively unsubscribing that component from model updates. As with subscribe, no cleanup is performed by store – for most use cases, use functions within the component module.

Search Document