Props
Props are what a parent passes in. They arrive on this.props.
export class Greeting extends Component<{ name: string }> {
render() {
return <p>Hello {this.props.name}</p>;
}
}
<Greeting name="Ada" />
The type parameter is the props type. It is not optional in practice — it is what makes the call site check.
They are read-only, and they throw
this.props.name = "Grace"; // TypeError, RMD004
Not a warning. Assigning throws in every build, development and production alike, because the alternative was worse: the write used to land nowhere and vanish, so reading the value back gave the old one and nothing ever said the assignment had been dropped.
If you need to change it, you have two options and they are the honest ones:
- Copy it into your own state.
@state name = this.props.namein@create, then it is yours. - Ask the parent. Take a callback prop and call it.
export class Row extends Component<{ item: Item; onRemove: (id: string) => void }> {
render() {
return <button onClick={() => this.props.onRemove(this.props.item.id)}>remove</button>;
}
}
Hook options work the same way and throw the same way (RMD015) — one rule for read-only
inputs, not two.
Reads are per key
this.props.name subscribes to name, not to the whole props object. A component that reads
only name does not re-render when the parent passes a new title.
Reacting to a prop changing
Sometimes derived state has to be recomputed when a specific prop moves. @watchProp does that
before the render, so the derived value is already correct when render() runs — with no
second pass.
@watchProp((props: UserProps) => props.userId)
reload(next: string, previous: string) {
this.data = undefined;
void this.fetch(next);
}
showing adano change yet — @watchProp does not fire on mount
Three things about it:
It does not fire on mount. Only on a change. Use @create for the initial case — which is
usually what you want anyway, since the two do different work.
Type it by annotating the selector's parameter, as above. That fills in both the props type
and the value type by inference. An explicit generic (watchProp<UserProps>(...)) does not
work: TypeScript has no partial inference, so naming one drops the other and the method's
parameters fall back to unknown.
A selector, not a string. It can reach as deep as you like — p => p.filters[0].value — and
it is checked by the compiler, which a string could never be.
@watchProp or @effect?
Both can respond to a change. They differ in when.
| runs | costs | |
|---|---|---|
@watchProp |
before the render | nothing extra |
@effect |
after the commit | its write causes another render |
Use @watchProp for derived state. Use @effect when the response is a side
effect — a subscription, a fetch, a measurement.
Children
children is an ordinary prop.
export class Panel extends Component<{ children?: RamondaNode }> {
render() {
return <section className="panel">{this.props.children}</section>;
}
}
Next
- Lifecycle —
@create,@mount,@destroy, and their order.