Skip to content

Batching and untracked

Batching

Writes flush immediately, so two writes in a row expose the state between them. Signal.batch defers the flush to the end of the block - effects run once, seeing only the final state:

open Fable.Ripple

let first = Var.create "Ada"
let last = Var.create "Lovelace"

// Runs immediately: Ada Lovelace
Signal.effect (fun () -> printfn "%s %s" first.Value last.Value) |> ignore

first.Value <- "Grace" // Grace Lovelace - a torn state
last.Value <- "Hopper" // Grace Hopper

// One flush at the end: Alan Turing
Signal.batch (fun () ->
    first.Value <- "Alan"
    last.Value <- "Turing"
)

Batches nest: the flush happens when the outermost one ends.

Every on.* handler in Fable.Ripple.Dom already batches its writes, so one user gesture is a single flush.

Three sources feed one subscriber. Unbatched, each write is its own flush: three dots, and the counter moves by three. Batched, the same writes reach the subscriber once:

Untracked reads

Three forms, one behaviour - read the current value without becoming a dependent:

  • myVar.Peek() - one read, on the source itself.
  • Signal.peek s - the same, on a Var or a Signal alike.
  • Signal.untracked f - a whole block, for when the reads are buried in a helper you did not write.
open Fable.Ripple

let query = Var.create "signals"
let page = Var.create 1

Signal.effect (fun () ->
    printfn "searching '%s' (page %d at the time)" query.Value (Signal.peek page)
)
|> ignore

page.Value <- 2 // peeked, not tracked - nothing runs
query.Value <- "adaptive" // searching 'adaptive' (page 2 at the time)

The effect reads page without depending on it, so writing page reruns nothing. Writing query reruns the effect, and it sees the current page.

Edit this page