Effect
Side effects that run when their dependencies change, with automatic cleanup.
Side effects that automatically re-run when their dependencies change.
Creating Effects
#Effect.run(fn)
#Creates and immediately runs an effect. The effect re-runs whenever any signal or computed it reads changes.
let count = Signal.make(0)
let disposer = Effect.run(() => {
Console.log(`Count is: ${Signal.get(count)->Int.toString}`)
})
// Logs: "Count is: 0"
Signal.set(count, 1)
// Logs: "Count is: 1"Effect.run(~name, fn)
#Creates a named effect for debugging.
Effect.run(~name="logger", () => {
Console.log(Signal.get(count))
})Cleanup Functions
#Effects can return a cleanup function that runs before the effect re-runs and when the effect is disposed.
let count = Signal.make(0)
Effect.run(() => {
let value = Signal.get(count)
Console.log(`Setting up for: ${value->Int.toString}`)
// Cleanup function — runs before next execution
Some(() => {
Console.log(`Cleaning up for: ${value->Int.toString}`)
})
})
Signal.set(count, 1)
// Logs: "Cleaning up for: 0"
// Logs: "Setting up for: 1"Disposal
#disposer.dispose()
#Effect.run returns a disposer object. Call dispose() to stop the effect and run any cleanup function.
let disposer = Effect.run(() => {
Console.log(Signal.get(count))
Some(() => Console.log("Cleanup!"))
})
// Stop tracking and run cleanup
disposer.dispose()
// Logs: "Cleanup!"
// Future changes won't trigger the effect
Signal.set(count, 100) // Nothing loggedCommon Use Cases
#DOM Updates
#let title = Signal.make("Hello")
Effect.run(() => {
let el = Document.getElementById("title")
el->Element.setTextContent(Signal.get(title))
None
})Event Listeners
#let isActive = Signal.make(false)
Effect.run(() => {
if Signal.get(isActive) {
let handler = _ => Console.log("Clicked!")
Window.addEventListener("click", handler)
Some(() => Window.removeEventListener("click", handler))
} else {
None
}
})Timers
#let interval = Signal.make(1000)
Effect.run(() => {
let ms = Signal.get(interval)
let id = setInterval(() => Console.log("Tick!"), ms)
Some(() => clearInterval(id))
})Local Storage Sync
#let theme = Signal.make("light")
Effect.run(() => {
let current = Signal.get(theme)
LocalStorage.setItem("theme", current)
None
})Was this page helpful?