Components and JSX
Askr components are plain functions returning JSX, with no compiler-owned reactivity and no hidden re-render rules.
Example
Put reactive state inside the component that owns the interaction and derive display values from it during render.
import { derive, state } from '@askrjs/askr';
export function Quantity() {
const [count, setCount] = state(1);
const label = derive(() => 'Quantity: ' + count());
return <button onClick={() => setCount((value) => value + 1)}>{label()}</button>;
}Function components
A component is any function matching (props: Props, context?: ComponentContext) => JSXElement | VNode — it takes a props object and optionally a context carrying an AbortSignal and SSR details, and returns something renderable. There's no required base class or decorator; naming it with a capital letter is what tells JSX to treat it as a component instead of an intrinsic tag like div.
Props and children
Props arrive as a single object, typed loosely as Props — an index signature that accepts arbitrary attributes plus a children slot — so components can accept whatever shape makes sense for them. children isn't restricted to a single type: it can be a JSX element, a string, an array, or a function, and it's up to the component to decide what to do with it. Because props are just an object, spreading, defaulting, and destructuring work exactly the way they do anywhere else in TypeScript.
JSX runtime
Askr ships its own JSX transform, published from @askrjs/askr/jsx-runtime and @askrjs/askr/jsx-dev-runtime, along with a Fragment export for <>...</> grouping. Your build tooling needs jsxImportSource (or the equivalent tsconfig jsx/jsxImportSource fields) pointed at @askrjs/askr so JSX compiles to Askr's jsx/jsxs calls rather than React's. The intrinsic element types — div, button, input, and friends — are typed individually in the runtime's KnownIntrinsicElementProps, so props like href on <a> or checked on <input> are checked against the real HTML attribute, not a generic bag.
Composition
Because components are just functions returning JSX, composing them is normal function composition: nest a component inside another's JSX, pass callbacks and derived values as props, or wrap children with a boundary component like ErrorBoundary. There's no special API for higher-order components — wrapping one component to add behavior is a function that takes a component (or props) and returns JSX, the same pattern you'd use in any functional codebase.