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.
- Import the published @askrjs/askr entrypoint.
- Keep determinism and runtime rules configuration next to the component, route, or server composition root that owns it.
- 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.