Skip to content

Coming from a component framework

ts2 has React’s shape: components are functions returning markup, props flow down, state is read with a hook and null draws nothing. The differences:

Reactts2
Dependency arraysNone; the build reads dependencies from the code
Rules of HooksNone; a hook may sit in a condition, a loop or a helper
key on list itemsNone; position is identity
Re-render, then diffUpdated in place
Callback propsNone; a child changes another component through a Ref prop
ContextA module-level cell, readable from anywhere
useMemo, useCallback, React.memoNot needed
CSS, className, styleProps: color, font, sprite, transparency
  • A redraw when a value changes: read it in the render.
  • A handler when a value changes: useWatch.
  • Time: useInterval and useDelay.
  • After the tree exists: onMounted and onUpdated, whose reads follow nothing.
  • Fetching: nothing is asynchronous; the game state is already there.

A setter works from a component that never reads the value, or from a function the server calls:

src/idiomatic.ts2
export const bossHudPin = (pinned: Int): void => {
const [, setPinned] = useState(bossHudPinned);
setPinned(pinned);
};

useState(0) is per instance and holds a whole number. useState(someCell), with a module-level declaration, is shared, which fills the place of context.

A prop a component does not declare lands on its root element, so this row sits at the y the caller gave, though StockRow declares no y:

src/shop.ts2
<StockRow item={row.item} name={row.name} price={row.price} stock={row.stock} y={4 + i * ROW_H} />

An onClick does not fall through; put it on a <layer> around the call.

useRef is a handle to a component, with no .current. It is how one component changes another, such as a scrollbar moving what it scrolls:

src/chrome.ts2
export const Scrollbar = ({ content }: { content: Ref }): Component => {

A rebuild discards ref writes, as a remount does. A change that must survive belongs in state.

The editor names what to use instead:

left outuse
DecimalsInt; a percentage is out of 100
for, break, continuewhile, or .map() over a list
Classes, objects built while runningrecords in a collection; object literals at module scope
Arrays built while runningconstant arrays, collections, containers
Functions as valuesa Ref prop
throw, trynothing; there is no failure to catch
async, Promisetimers, and a read of a value that arrives later
Truthiness, ==stock > 0, ===
Most string methodseleven operations and the template literal