:title
14. Coming from React

:content
If you have written React, most of what you know transfers — the parts that change are where rendering happens and what a component is allowed to hold.

Capy renders on the server. A unit is a `.capy` file, a page is a `function RENDER`, and the output is HTML written with `print`. There is no virtual DOM, no client bundle, and no file-system router unless you write one.

## The mapping

| React | Capy |
| --- | --- |
| a page component | `function RENDER()` |
| a reusable component | `function COMPONENT(props : dval)` |
| several components in one file | `function COMPONENT:NAME(props : dval)` |
| `props` | `props` |
| `return <div>…</div>` | `print(…)` |
| rendering a child | `component_render("card")` or `component("card")` |

A handler returns nothing. Whatever it prints becomes the response, so the React habit of building a tree and returning it becomes writing output in order:

:example capy render
function RENDER()
{
	var name := string(request.query.name, fallback: "guest")
	print("<main><h1>Hello, ", name, "</h1>")
	print("<p>Rendered on the server.</p></main>", "\n")
}

:output
<main><h1>Hello, guest</h1><p>Rendered on the server.</p></main>

:content

## Components take explicit props

A React component receives props as an object and can render children. A Capy component receives a `props` parameter and has no children or slots. Pass inner content as a prop or call another component.

:example capy component
function COMPONENT(props : dval)
{
	var title := string(props.title, fallback: "Untitled")
	print("<article><h3>", title, "</h3></article>")
}

:content

The caller decides how the result is used. `component_render()` writes the fragment straight into the response, which is the common case in a layout. `component()` returns it as a string when you need to wrap, measure, or conditionally emit it.

Each component call passes its own props argument. Props are shared objects, so changes to their contents remain visible to the caller.

## There is no client state

This is the biggest adjustment. There is no `useState`, no effect hook, and no re-render — a handler runs once per request and produces final HTML.

What replaces them:

- Per-request shared state uses application keys such as `request.user`, readable by every handler in the request.
- **work that runs once before a unit's handlers** — `function ONCE()`
- **work that runs once when a worker loads a unit** — `function INIT()`
- **state that outlives the request** — a session, a file, a database, or a task

A module handle from `unit_load()` lives only for the current request; do not stash one for later.

## Escaping

HTML literals escape interpolated values, like React escapes `{value}` by default:

:example capy render
function RENDER()
{
	var supplied := string(request.query.q, fallback: "<script>")
	print(<><p><?= supplied ?></p></>)
}

:content

Use `html_escape()` when you are building a string by concatenation instead.

## What Bearer deliberately does not have

No asset registry, no island registry, no JSX-style component tags, no built-in children or slots. Routing is application code — the starter example checks page files and parent index handlers, which keeps the rules visible rather than implied by directory layout.

## When something does not compile

Bearer reports the source path and the compiler output, and writes the full output under `BIN_DIRECTORY`. A compile error names the unit and line, not a bundler stack.

:see-group
guides

:see
>handler/render
>handler/component
>type/request
component
component_render
