Functions & Bindings
let still handles values and reusable functions. The action keyword introduces reusable action-shaped records, and component is for element-style declarations that need emitted actions or persistent local state.
Element-style functions
Section titled “Element-style functions”type User = { name:string avatarUrl:string }
let <UserCard user:User tone:string = "neutral"/> = <div className={"card " + tone}> <img src={user.avatarUrl}/> <h3>{user.name}</h3> </div>
let currentUser = <User name="Ada" avatarUrl="/ada.png"/>
<UserCard user={currentUser} tone="info"/>- Attributes in the signature declare names, types, and defaults.
- Invocation mirrors the signature: supply values instead of types.
Component declarations
Section titled “Component declarations”action SearchSubmitted = { searchString:string}
action DoSearch = { search:string}
component <SearchBox placeholder:string emits { ValueChanged { value:string } SearchSubmitted }/> = { state { query:string = {placeholder} }
<TextInput value={query} placeholder={placeholder} />}
action TrackSearch = { value:string}
let makeValueChanged(value:string): SearchBox.ValueChanged = <SearchBox.ValueChanged value={value} />
<SearchBox placeholder="Find docs" onSearchSubmitted=<DoSearch search={action.searchString}/> onValueChanged=<TrackSearch value={action.value}/> />- Use
actionfor shared action contracts that multiple components can emit. - Use
componentwhen the declaration needsemitsorstate. emitscan declare a new action inline or reference an existingactionby name.- Inline emitted actions become public action names such as
SearchBox.ValueChanged. - Component invocation sites can bind emitted actions through
on<ActionName>properties with an implicitactionvalue inside the handler body. - Hosts initialize components by name, receive the rendered output plus an opaque state snapshot, and later dispatch ordered action batches with that saved snapshot.
- State defaults run only during initialization. After that a handler changes state by returning the component’s update record, written
<Update ... />inside the component; it names only the fields that change. - Inside a component a handler may return its own
Updateor an action the componentemits; at the root any action or update record goes to the host.
external component <Button label:string emits { Tapped { } } />
component <Counter /> = { state { count:int = 0 } <Row> <Label text={count} /> <Button label="Add" onTapped=<Update count={count + 1} /> /> </Row>}Every record also has an update record, so the same patch shape works outside components:
<User.Update email={} /> clears email — the field is present and empty, which is allowed only
for an optional field such as email?:string — and leaves every other field alone. See
Updating state.
A field can also be named as a value. User.Property.email is a case of the derived constant union
User.Property, so a sort key or a column list is typed by the fields that exist, and inside a
component a bare Property names the component’s own. Four intrinsics work on any update record:
apply(record, update), merge(first, second), diff(before, after), and changed(update), which
lists the present fields as User.Property cases. See
Property references.
Paren-style functions
Section titled “Paren-style functions”let formatName(name:string, title?:string): string = { if title? { title + " " + name } else { name }}
let displayName = { formatName("Ada", "Dr.") }let plainName = { formatName("Ada") }Use this form for small, general-purpose helpers that compute a value and read naturally with
parentheses, such as min, floor or rgb. A function that produces markup uses the element
style, even when it takes a single parameter. A paren-style function can also be called as an element,
<formatName name="Ada" />; an element-style function is called only as an element.
Parameters a caller may leave out — optional (title?:string) or defaulted (sep:string = ", ")
— come last, and a call may stop before them. The function fills each one it is not given: with
its default, which it evaluates itself, or with {}.
Constants
Section titled “Constants”let primaryTone = "info"let spacing = 12let binds any expression to a name; use explicit types when inference isn’t obvious.
See also (Reference/Grammar)
Section titled “See also (Reference/Grammar)”- Reference: Functions & Components
- Reference: Modules
- Grammar: nx-grammar.md – Functions