Try Install Learn Blog API Packages GitHub
Posts

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 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 returns a
  • Function(Html.Event,a) which takes an Html.Event and returns a

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 🙏