Events and State Friday, April 26th, 2019
In this post I will show you how to use events and the internal state of components 🙂
Events
Every web application leverages events to handle change in its state, such events can come from a couple of different sources:
- user interaction from DOM nodes
- interactions from the browser itself
- interactions from a server (for example from a WebSocket connection)
- and possibly other sources
I will show you how to handle events that come from DOM nodes.
Event attributes and handlers
As in React, DOM nodes can have event attributes attached to them: every
attribute which starts with
on
is an
event attribute (
onClick
,
onMouseOver
, etc...)
Since Mint uses React as platform you can refer to its documentation on the list of supported events.
Event attributes values are functions which must match one of the following two types:
-
Function(a)
which returnsa
-
Function(Html.Event,a)
which takes anHtml.Event
and returnsa
a
is a type variable which means it can be any other type.
For example both handlers are valid in this example:
component Main {
fun increment (event : Html.Event) : String {
Debug.log("Increment")
}
fun decrement : String {
Debug.log("Decrement")
}
fun render : Html {
<div>
<button onClick={decrement}>
"Decrement"
</button>
<button onClick={increment}>
"Increment"
</button>
</div>
}
}
When clicking on a button you will see
increment
or
decrement
in the console depending on which button you clicked.
As you can see you can reference the function itself without calling it, just by its name.
Html.Event
The
Html.Event
type is a normalized version of the
DOM Event
interface, you can see the actual type definition
here.
Internal State
Components can have their own state to achieve some specific functionality which does not require a global state.
A
state
can be defined using the
state
keyword similarly to the
property
keyword:
component Main {
state count : Number = 0
...
}
This state can be used across the component just by referencing it:
...
<button onClick={decrement}>
"Decrement"
</button>
<{ Number.toString(count) }>
<button onClick={increment}>
"Increment"
</button>
....
Modifying State
A state (or multiple ones) can be set using the
next
keyword: it tells the component to replace the given states with new values.
States don't mutate but get replaced because data-structures in Mint are immutable.
For example we modify our functions to update the count:
...
fun increment : Promise(Never, Void) {
next { count = count + 1 }
}
fun decrement : Promise(Never, Void) {
next { count = count - 1 }
}
...
Notice that the return type of the function has changed to
Promise(Never, Void)
Promises are used in asynchronous computations (which we will touch in the next post) and modifying state returns a promise because it is considered a side-effect.
A promise has two parameters, the first is the error type in this case it's
Never
to indicate it can't fail and the second is the type of the return value when
it resolves, in this case it's
Void
meaning its not relevant (basically cannot be used for anything).
That's it for today, thank you for reading 🙏