MXML
The MXML language, as part of the Apache Flex framework, was used for describing UI components in an intuitive way. ShockScript uses XML constructs semantically similar to the ReactJS + JSX technologies, but designed to feel close to MXML.
HelloWorld.sx
package zero {
import whack.ds.UIComponent;
import s = spark.components.*
public class HelloWorld extends UIComponent {
public function HelloWorld() {
super()
final = (
<s:Application>
<s:Label>Hello World!</s:Label>
</s:Application>
);
}
}
}
Event handlers
In MXML, event handlers were expressed as e="statements". In ShockScript, they are expressed as e&={statements} (note the ampersand &) as a shorthand to e={function(event){statements}}.
Note: Although not demanded as such, as opposed to ReactJS + DOM, event handlers are conventionally expressed without a
onprefix, such asclick&={trace("clicked!")}rather than ReactJSonClick={e=>{console.log("clicked!")}}. Event props are conventionally given the@eventtag in the ShockDoc comments. Classes continue using theEventmeta-data, though without needing the@eventTypetag.
Rendering components
The Whack DS framework allows programmers to implement UI components as throwaway classes that wrap around the DOM elements of Whack Engine. The component is rendered by constructing the class initially and whenever states, props and/or contexts change.
Effects
Effect hooks like whack.ds.useEffect may be used to run code when specific Props, State or Context change, or solely for running code during the component mount and unmount phases.
The effect dependencies — States, Props and Contexts it relies on — are auto-tracked as the effect function evaluates.
whack.ds.useEffect(function() {
// Cleanup
return function() {
//
};
});
// Effect that runs everytime (*)
whack.ds.useEffect(function() {
//
}, "*");
When there are no dependencies, the hook is equivalent to a component mount/unmount event, with the unmount phase handled through the returned function.
whack.ds.useEffect(function() {
// Did mount
return function() {
// Unmount
};
});
Callbacks
Similarly to effects, callbacks that appear in E4X literals applied to the whack.ds.Node type auto track dependencies, since they are cached for aiding on memoization.
States
Declare State variables using the State meta-data:
public class Main extends UIComponent {
[State]
var counter : uint = 0;
}
The initial value of counter is zero, although that initializer evaluates only the first time the component renders.
Overwriting a state with a different value (as by an equals comparison) will indirectly re-render the component.
Note that, like with ReactJS, arrays and structures as states will not trigger a re-render during push like operations; instead the programmer needs to reconstruct the object, as in:
x = [...x, 10]
Bindables
In the top-level of a Whack DS component, declare bindables by using the Bindable meta-data. Bindables have certain use-cases, such as persisting a value across renders, and extracting DOM elements from certain tags (in which case the bind attribute is used).
public class Main extends UIComponent {
[Bindable]
var button : org.w3.web.Button? = null;
public function Main() {
super()
final = (
<button bind={button}>Click me</button>
)
}
}
Contexts
Obtain inherited contexts by using a Context variable.
public class Main extends UIComponent {
[Context("spark.contexts.Theme")]
const theme;
public function Main() {
super()
final = (
<></>
)
}
}
Capture safety
Unlike in ReactJS combined with TypeScript, states, bindables (“refs”) and context values (if following the recommendations) are captured by reference from nested functions, guaranting the “outdated” value of, say, a state, is never captured, which facilitates development by requiring no additional Bindable declaration.
Props are also safe to use anywhere within the component as long as you follow the recommendations (such as avoiding destructuring it in large method bodies).
Styling
Unlike with ReactJS, there is built-in support for linking style sheets in a Whack DS component.
<div>
<fx:Style>
<![CDATA[
root {
background: red
}
]]>
</fx:Style>
</div>