Askr
Fundamentals

Determinism and Runtime Rules

Use determinism and runtime rules with the current published Askr packages.

  • @askrjs/askr0.0.59

How to use determinism and runtime rules

Put reactive state inside the component that owns the interaction and derive display values from it during render.

  1. Import the published @askrjs/askr entrypoint.
  2. Keep determinism and runtime rules configuration next to the component, route, or server composition root that owns it.
  3. Handle pending, unavailable, cancellation, and failure states, then verify the production path.
import { derive, state } from '@askrjs/askr';

export function Quantity() {
  const count = state(1);
  const label = derive(() => 'Quantity: ' + count());

  return <button onClick={() => count.set(count() + 1)}>{label()}</button>;
}

Render purity

A component function must return the same output for the same props and state on every call — the runtime depends on this to decide what changed and patch only that part of the DOM. Fetching data, subscribing to external events, or mutating shared objects directly inside a component body breaks that guarantee; those belong behind `resource`, `on`, or `task` instead, which run outside the render pass and hand results back through reactive values.

Stable initial state

`state()` initializers run once, on first render, and are expected to be pure — if the seed value depends on something nondeterministic (like `Math.random()` or `Date.now()`), server-rendered markup and the client's first hydration pass will disagree. Deriving that value from a stable input (a route param, a server-supplied seed) instead keeps the first render identical on both sides.

Browser-only work

Code that touches `window`, `document`, or other browser globals can't run during server rendering, since none of those exist in a Node process. Gate that work behind lifecycle helpers like `task` or `resource`, which only execute after mount on the client, rather than reading browser globals directly in the component body where SSR would throw.

Hydration diagnostics

Server-side rendering shares a `DocumentRenderContext` — including a `seed` value — with the client so both passes render the same output from the same inputs; when they disagree, the runtime surfaces a hydration mismatch. Development builds emit diagnostics tied to `devWarningsEmitted` on the component instance to help point at which subtree diverged, so a mismatch shows up as a specific warning rather than a generic "hydration failed" message.