brumate

State

State is the data of a component that can change in the browser. $signal declares a value that you write, and $memo declares a value that is computed from other values.

App.brmEdit the code to run it again

The sample runs when it comes into view.

$signal

$signal(value) declares writable state. The variable is the value: read it like any variable, and assign to it to change it.

<script>
  import { $signal } from 'brumate/signals';

  let name = $signal('Ada');
  let tags = $signal<string[]>([]);
  let selected = $signal<number>();
</script>
App.brmEdit the code to run it again

The sample runs when it comes into view.

Where you can write a signal

A signal can be written in code that runs in the browser:

Code that runs while the component renders cannot write a signal. Its value at render time is the value that the page starts with, so a later write there would have no effect. The compiler reports it:

<script>
  import { $signal } from 'brumate/signals';

  let count = $signal(0);
  count = 5;
</script>
Signal "count" can only be written in event handlers, effects, $client callbacks and functions (App.brm:5:3)

Compute the starting value in the call instead: let count = $signal(5).

$memo

$memo(expression) declares a value that is computed from other values. When a value that it reads changes, the memo computes again.

App.brmEdit the code to run it again

The sample runs when it comes into view.

A memo can also hold a promise, such as the result of a server function. Async data covers that.

$produce

A signal changes when you assign a new value. To change one item of an array or one field of an object, $produce gives you a draft that you can change in place, and writes the result as a new value:

App.brmEdit the code to run it again

The sample runs when it comes into view.

Without $produce, write a new value yourself: todos = todos.map((todo) => (todo.id === id ? { ...todo, done: !todo.done } : todo)).

$untrack

$untrack(expression) reads values without depending on them. The memo or effect around it does not compute again when they change.

Here the list follows the filter as you type, but a new page size only applies with the next change of the filter:

App.brmEdit the code to run it again

The sample runs when it comes into view.

$untrack also covers the functions that the expression calls. Effects shows why that matters.

Rules and common mistakes

What the browser gets

The server renders the page with the values of every signal and memo. The browser only gets the values that its code reads, such as a signal that a handler writes and the memos that read it. A signal that no code in the browser writes stays on the server, and the page shows it as plain HTML.

What runs where explains which code and values the browser gets.