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

Props and children

How a prop stays current while the child runs once, how a callback prop talks back, and where children go.

Last page, a list repeated markup. Repeated markup often becomes its own component, and components talk through props.

Pass count to a child, and the child stays current. Yet the child body still runs only once.

A component’s parameter is its props. A prop reads the parent’s current value, not a copy. When count changes, Markless updates the text inside the child, and the child body stays put.

Click the number button in the page.

Does Badge run again when its prop changes?

Click the number button in the page a few times. Watch Times Badge ran.

The pageTry it
Counter

The page's HTML right now

<button> <strong class="badge">0</strong> </button>
Your code: Counter.tsrx
import { state } from '@markless/core'; function Badge({ value }: { value: number }) @{ (ran once) <strong class="badge">{value}</strong> (shows the prop)} export default function Counter() @{ (ran once) let count = state(0); <button onClick={() => count++}> (runs on click) <Badge value={count} /> (passes count) </button>}
What Markless did
Times Counter ran1
Times Badge ran1
Texts changed in Badge0
  1. ranRan Counter once, to build the page.
  2. ranRan Badge once, with value 0.

Simplified. The HTML view shows the elements the two components made. Yellow marks the only text that changed.

Notice that Times Badge ran stays at 1.

Pass a prop

import { state } from '@markless/core';

function Badge({ value }: { value: number }) @{
	<strong class="badge">{value}</strong>
}

export default function Counter() @{
	let count = state(0);

	<button onClick={() => count++}>
		<Badge value={count} />
	</button>
}

For this file, a click plans one update: the text inside <strong>. Nothing calls Badge again.

Talk back with a callback

import { state } from '@markless/core';

function Picker({ onPick }: { onPick: (name: string) => void }) @{
	<button onClick={() => onPick('Ada')}>Pick Ada</button>
}

export default function Page() @{
	let picked = state('nobody');

	<section>
		<p>Picked {picked}</p>
		<Picker onPick={(name) => (picked = name)} />
	</section>
}

A callback prop takes zero or one parameter. Two or more fail with MARKLESS_CALLBACK_PROP_ARITY_UNSUPPORTED. To send more, pass one object.

Children

Markup between a component’s tags arrives as children. Place it with {children}. Type it with Children from @markless/core.

import type { Children } from '@markless/core';

export function Card({ title, children }: { title: string; children?: Children }) @{
	<section class="card">
		<h2>{title}</h2>
		{children}
	</section>
}
Coming from another framework?

In React, a new prop value calls the child function again. Here the child function runs once. Markless writes the new value into the one spot that shows it.

Next: How do you style Badge without the CSS leaking into other files? Styles →

Was this page helpful?