React.js
ShockScript incorporates XML capabilities, and XML expressions allow for implementations to produce anything desired, similiar to JSX. There are certain differences to JSX or React.js.
The following demonstrates a basic XML expression for Jetâ„¢:
<j:HGroup>
<j:Button click&={trace("clicked!")}>button 1</j:Button>
</j:HGroup>
Event handlers
In ShockScript, event handlers are expressed as e&={statementList}
(note the ampersand &) as a shorthand to e={function(event){statementList}}
. Furthermore, event handlers are conventionally expressed without an on
prefix (for instance, click
instead of onClick
), and they are documented with the @eventparam
tag.
Prefixes
ShockScript allows for <q:N>
, whose name resolution equals q::N
. Dots may be used for entities other than namespaces, as in:
<com.business.components.AppBar/>
For brevity, you do either:
import bc = com.business.components.**;
<bc:AppBar/>
or:
import com.business.components.*
<AppBar/>
Interpolation
Interpolation works similiarly to React.js, except for HTML.
<j:VGroup>
{undefined}
{null}
{node}
{nodeList}
{plainText}
{number}
</j:VGroup>
Interpolating attributes uses { object }
and not { ...object }
and must appear at most once at the end of all attributes:
<j:Button {params}>click me</j:Button>
States
Unlike React.js, in Jet+Spot there is no risk of accessing an outdated state's value, due to how states are constructed.
package com.business.components {
//
public function HelloWorld() {
[State]
var x:decimal = 0;
return (
<j:VGroup>
<j:Label>clicked {x} times</j:Label>
<j:Button click&={x++}>click me</j:Button>
</j:VGroup>
);
}
}
The state's initializer represents the state's initial value.
Like React.js, there is no transitive detection of mutation methods; therefore, the following is necessary over an array .push(v)
:
x = [...x, v];
As to Map objects:
m = { ...m, k: v };
References
In Jet+Spot the concept of "refs" is more formally called references.
package com.business.components {
//
public function HelloWorld() {
[Reference]
var button:Button?;
//
Spot::useEffect(function() {
trace(button!);
}, []);
return (
<j:Button bind={button}>click me</j:Button>
);
}
}
Contexts
Context usage is represented as Spot::ContextReflection.<T>
objects, although they are used as natural Context
-annotated locals.
function ExampleComponent() {
//
[Context(ExampleContext)]
const example:Number;
return (
<></>
);
}
Effects
The popular "useEffect" hook requires the second argument, preventing mistakes. For listening to any changes, use "*"
.
Spot::useEffect(function() {
//
return function() {
// cleanup
};
}, [dep1, ...depN]);
Spot::useEffect(function() {
//
}, "*");
Styling
Unlike with React.js, there is built-in support for linking style sheets in a Spot component.
<j:Container>
<j:Style>
<![CDATA[
:host {
background: red;
}
]]>
</j:Style>
</j:Container>