// Template function — no outer function, no atoms.
// The entire function re-runs with the parent.
const LikeCount = ({ likes }) => html`
<span>♥ ${likes}</span>
`;
// Caller reads its own atom and passes the value:
// html`… ${LikeCount({ likes: likes() })} …`
Overview
A component is a setup function that returns a template function. A template function is just the template function — the inner layer with nothing around it. It takes a props object and returns an html result directly.
Because there is no outer function, a template function cannot own atoms or lifecycle hooks, and it has no scheduler slot of its own: whenever the parent re-renders, the call re-executes and rebuilds its fragment. State must come in as props.
Because there is no scheduler, you call it directly — Badge({ label }) — exactly like any other function. No x() wrapper. It composes anywhere: inside .map(), in helper modules, as an argument.
Template function vs component
|
Capability
|
Template function
|
Component (outer/inner)
|
|---|---|---|
| Local reactive state | none |
Use atom() only in components.
|
| Lifecycle hooks | none |
onMount, onCleanup require a component outer function.
|
| Independent re-rendering | runs with parent | Re-executes on every parent render. Components re-render only when their own dependencies change. |
| Composition style | Direct call |
Call as Badge({ label }). Components need x(Component, props).
|
| Props destructuring | safe | No outer/inner split — destructuring in the function body is always up-to-date. |
Stateless Badge and UserRow template functions
Badge and UserRow take plain objects and return html``. No lifecycle, no state — just a function. Call them directly in a map() or anywhere in a parent template.
Parent owns state; template function presents
Status is a pure template function. The parent atom drives updates — Status re-runs whenever the parent template re-renders.