---
title: Events
description: Run code on clicks, typing, and other browser events with onClick and the other on-props.
---

Shared state gave two components one `count`. Something still has to change it. That something is an event, like a click.

**Misconception: the browser must download every click handler before the page works.** At build time, the compiler puts each handler in its own chunk. The code for a click loads the first time someone clicks.

This is true wherever the page renders: in the browser alone, or on a server.

Click the button in the figure twice. Then type a new name.

<StateEventFigure />

Notice that the first click loads the click code, and the second click reuses it. Typing loads its own code, on the first key press.

```tsrx Greeter.tsrx
import { state } from '@markless/core';

export default function Greeter() @{
	let name = state('Ada');
	let count = state(0);

	<form onSubmit={(event) => event.preventDefault()}>
		<input value={name} onInput={(event) => name = event.currentTarget.value} />
		<button type="button" onClick={() => count++}>{name} clicked {count}</button>
	</form>
}
```

An event prop is `on` plus the browser event name. Case after `on` does not matter: `onKeyDown` and `onKeydown` both listen for `keydown`. Your handler gets the browser's event object.

To run two handlers on one event, pass an array: `onClick={[first, second]}`. They run in the order you write them.

:::warning[Why can't my handler read this variable?]
A handler can read state, props, imports, and `const` values built from those. Other body variables give `MARKLESS_HANDLER_READS_RENDER_LOCAL`. Your component runs once, so those variables do not exist when the click comes.
:::

:::danger[Why does preventDefault() inside an if fail the build?]
The browser must decide `preventDefault()` before the click code finishes loading. So the compiler checks the `if` condition ahead of time. A condition like `open && event.key === 'Enter'` works. If the compiler cannot check it, you get `MARKLESS_SYNC_POLICY_UNEXTRACTABLE`.
:::

Want the technical version? See [Lazy chunks](/how-it-works/lazy-chunks).

**Next:** How does a handler reach the real `<input>` to focus it? [Elements →](/state/elements)
