A signal is a getter/setter pair. Reading the getter inside an effect subscribes that effect; writing the setter re-runs it. The compiler finds which DOM nodes read which signals and wires one effect per node, so setCount(1) updates exactly the text node, attribute, or list row that reads count(). Components run once — there is no re-render and no virtual DOM.
All primitives are imported from @barefootjs/client:
"use client"
import { createSignal, createEffect, createMemo, onMount, onCleanup, untrack, batch } from '@barefootjs/client'"use client"
import { createSignal, createMemo } from '@barefootjs/client'
export function Counter() {
const [count, setCount] = createSignal(0)
const doubled = createMemo(() => count() * 2)
return (
<div>
<p>{count()} doubled is {doubled()}</p>
<button onClick={() => setCount(n => n + 1)}>+1</button>
</div>
)
}The getter is a function call — count(), not count. Dependencies are tracked from those calls; there are no dependency arrays. Clicking the button re-runs only the effect the compiler generated for the <p> text.
#API Reference
| API | Description |
|---|---|
createSignal |
Create a reactive value |
createEffect |
Run side effects when dependencies change |
createMemo |
Create a cached derived value |
onMount |
Run once on component initialization |
onCleanup |
Register cleanup for effects and lifecycle |
untrack |
Read signals without tracking dependencies |
batch |
Group signal writes so subscribers run once |
createQuery |
A value loaded by an HTTP request, seeded on the server |
createMutation |
A value written by an HTTP request sent on demand |
#Guides
- Props Reactivity — every way of reading a prop, including destructuring, is a live read
- Context API — sharing state between components