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:
| React | ts2 |
|---|---|
| Dependency arrays | None; the build reads dependencies from the code |
| Rules of Hooks | None; a hook may sit in a condition, a loop or a helper |
key on list items | None; position is identity |
| Re-render, then diff | Updated in place |
| Callback props | None; a child changes another component through a Ref prop |
| Context | A module-level cell, readable from anywhere |
useMemo, useCallback, React.memo | Not needed |
CSS, className, style | Props: color, font, sprite, transparency |
There is no useEffect
Section titled “There is no useEffect”- A redraw when a value changes: read it in the render.
- A handler when a value changes:
useWatch. - Time:
useIntervalanduseDelay. - After the tree exists:
onMountedandonUpdated, whose reads follow nothing. - Fetching: nothing is asynchronous; the game state is already there.
Setting state from anywhere
Section titled “Setting state from anywhere”A setter works from a component that never reads the value, or from a function the server calls:
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.
Undeclared props fall through
Section titled “Undeclared props fall through”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:
<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.
Refs are the normal tool
Section titled “Refs are the normal tool”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:
export const Scrollbar = ({ content }: { content: Ref }): Component => {A rebuild discards ref writes, as a remount does. A change that must survive belongs in state.
What the language leaves out
Section titled “What the language leaves out”The editor names what to use instead:
| left out | use |
|---|---|
| Decimals | Int; a percentage is out of 100 |
for, break, continue | while, or .map() over a list |
| Classes, objects built while running | records in a collection; object literals at module scope |
| Arrays built while running | constant arrays, collections, containers |
| Functions as values | a Ref prop |
throw, try | nothing; there is no failure to catch |
async, Promise | timers, and a read of a value that arrives later |
Truthiness, == | stock > 0, === |
| Most string methods | eleven operations and the template literal |