This the third post in a series that showcases the features of Mint, you can find the previous posts here:
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 it's 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).
Here is the full source, thank you for reading ๐:
component Main {
state count : Number = 0
fun increment : Promise(Never, Void) {
next { count = count + 1 }
}
fun decrement : Promise(Never, Void) {
next { count = count - 1 }
}
fun render : Html {
<div>
<button onClick={decrement}>
"Decrement"
</button>
<{ Number.toString(count) }>
<button onClick={increment}>
"Increment"
</button>
</div>
}
}
If you like to learn more about Mint check out the guide ๐
In the next part I'm going to show how to load and display data from a JSON API ๐ see you there ๐
Top comments (0)