# Read and update signals
Use writable, readonly, and computed values with synchronous batching.

## APIs demonstrated

- [signal](/reference/functions/signal/) from `@pibbl/core`
- [computed](/reference/functions/computed/) from `@pibbl/core`
- [batch](/reference/functions/batch/) from `@pibbl/core`
- [untracked](/reference/functions/untracked/) from `@pibbl/core`
- [isSignal](/reference/functions/is-signal/) from `@pibbl/core`
- [resolveSignalValue](/reference/functions/resolve-signal-value/) from `@pibbl/core`
- [Signal](/reference/types/canvas-runtime/) from `@pibbl/core`
- [WritableSignal](/reference/types/canvas-runtime/) from `@pibbl/core`
- [SignalValue](/reference/types/signal-inputs/) from `@pibbl/core`
- [SignalEquals](/reference/types/canvas-runtime/) from `@pibbl/core`
- [SignalOptions](/reference/types/canvas-runtime/) from `@pibbl/core`

## Complete example

[Plain source](/minimal/lifecycle/signals.ts). Run as a browser module after the document body exists. TSX uses `jsx: "react-jsx"` and `jsxImportSource: "@pibbl/core"`.

```ts
import {
  signal,
  computed,
  batch,
  untracked,
  isSignal,
  resolveSignalValue,
  type Signal,
  type WritableSignal,
  type SignalValue,
  type SignalEquals,
  type SignalOptions,
} from "@pibbl/core";

const equals: SignalEquals<number> = (a, b) => a === b;
const options: SignalOptions<number> = { equals, debugName: "count" };
const count: WritableSignal<number> = signal(1, options);
const readonlyCount: Signal<number> = count.asReadonly();
const doubled = computed(() => readonlyCount.get() * 2);
const input: SignalValue<number> = count;
const output = document.createElement("pre");
const button = document.createElement("button");
button.textContent = "Increment twice in one batch";
function show() {
  output.textContent = `Count: ${resolveSignalValue(input)}; doubled: ${doubled.get()}; is signal: ${isSignal(input)}; untracked read: ${untracked(() => count.get())}`;
}
button.addEventListener("click", () => {
  batch(() => {
    count.update((value) => value + 1);
    count.update((value) => value + 1);
  });
  show();
});
document.body.append(button, output);
show();

```

## Usage notes

- Untracked reads do not attach dependency edges. This example refreshes the DOM explicitly; Pibbl component reads subscribe automatically.

## Documentation version

Documentation built with @pibbl/core 0.0.2, revision 272a94a. ALPHA — NOT FOR PRODUCTION USE.
