# Behavioral Contracts

> Behavioral Contracts: published entrypoints, signatures, and the constraints around them.

Source: [https://askrjs.com/docs/reference/behavioral-contracts](https://askrjs.com/docs/reference/behavioral-contracts)

Status: stable. Packages: @askrjs/askr.

**Published packages are authoritative.** Examples may lag behind a published contract. When guidance differs, verify the exports and TypeScript declarations in your installed package, then file an issue.

## Example

Preserve ownership, cancellation, deterministic rendering, and delivery parity when composing lower-level APIs into application features.

```tsx
import { resource } from '@askrjs/askr/resources';

const project = resource(
  ({ signal }) => api.projects.get(projectId(), { signal }),
  [projectId]
);

// The component owns this request; disposal aborts it.
```

## Render contract

A component function is a `ComponentFunction`: it takes `Props` and an optional `ComponentContext` (carrying a `signal` and, during SSR, an `SSRContext`) and returns a `JSXElement` or `VNode`. Calling `state()` is only valid during that render call — it reads the active component instance from context, and calling it outside a component function throws, per the runtime's own guard.

## Ownership

Reactive scope is threaded with `defineScope()`/`readScope()` rather than any global mutable state — `defineScope(defaultValue)` creates a `Scope<T>` you provide via a wrapping element, and `readScope()` reads the nearest value down the component tree. Internally each mounted component tracks its own `ownerFrame`, `stateValues`, and cleanup functions, so state and scope values are torn down with the instance that created them.

## Cancellation

Every component receives an `AbortSignal` through its render context, and `ComponentInstance` holds the backing `AbortController` used to cancel in-flight work when the component unmounts. `resource()` (from @askrjs/askr/resources) is built on this — it passes the signal into your async function so a `fetch` or other cancelable call stops when the component goes away, instead of resolving into a dead component.

## Delivery parity

The same component tree renders through server rendering (SSR), static generation (SSG), and client hydration — the framework doesn't fork component behavior between server and client render paths. The two sides don't share one context type end to end, though: SSR and SSG document-wrapping share a `DocumentRenderContext` (mode: 'ssr' | 'ssg', url, params, seed, route), while the client's own render pass carries a separate `ActiveRenderContext` (mode: 'ssr' | 'spa') built specifically for hydration and client-only rendering. Hydration reconciles the server-rendered markup against the client's first render pass rather than re-rendering from scratch, so component output needs to be stable across both invocations for hydration to succeed cleanly.

## Documentation navigation

[Previous](https://askrjs.com/docs/reference/jsx-reference/index.md) | [Next](https://askrjs.com/docs/reference/testing-utilities/index.md)
