Why your component runs once
How a .tsrx component is built, which lines are TypeScript and which are markup, and why the body runs only once.
The tour showed you where the .tsrx files live. Now we open one.
The first time I saw @{, I thought it was a typo. Those two characters hold the whole idea.
A body that runs once
A component is a function with its body inside @{ ... }. The compiler plans every update before your app runs. So the body runs once, to set up the page, and never again.
Misconception: a component runs again each time something changes. Click Count a few times.
Does Counter run again when count changes?
Click Count a few times. Watch the two numbers under What Markless did.
import { state } from '@markless/core'; export default function Counter() @{ (ran once, in the browser) let count = state(0); <button onClick={() => count++}>Count {count}</button> (runs on click) (shows count)}- ranRan Counter once, in the browser, to build the page.
Simplified. A server is optional: in both choices, a click changes the same one text. The run counts follow the tests in packages/web/test/render.test.ts.
Notice that Times Counter ran stays at 1 while the number on the button climbs.
The compiler made that plan at build time, so it holds wherever the component renders. In the browser, the body runs once, right there. If you render the page on a server, the body runs once there and zero times in the browser.
What is TypeScript and what is markup
import { state } from '@markless/core';
export default function Counter() @{
let count = state(0);
<button onClick={() => count++}>Count {count}</button>
}
The lines above the markup are ordinary TypeScript. The markup goes straight into the body. Inside the markup, { } holds an expression, and @ starts a block such as @if or @for.
Import state and the other tools from @markless/core. A comment in markup is {/* ... */}, and it never reaches the page.
If you forget the @ before {, the compiler finds no markup. It warns that the file renders nothing.
Coming from another framework?
In React, a component returns JSX, and React calls the function again after each state change. A Markless body does not return markup to call again. The compiler reads it at build time and writes the updates out ahead. Then the body runs once.
Next: What else can go inside those braces? Markup and expressions →
