Skip to content
These are temporary community docs. The official docs are in progress.Help improve them
Markless
Esc
↑↓navigate↵open⌘Jpreview
On this page

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.

Where the page was made
The pageTry it
Countermade in the browser
Your code: Counter.tsrx
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)}
What Markless did
Times Counter ran1in the browser
Texts changed on the page0
  1. 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 →

Was this page helpful?