DEV Community

Cover image for Mint 🍃: Events and State of Components
Szikszai Gusztáv
Szikszai Gusztáv

Posted on • Updated on

Mint 🍃: Events and State of Components

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 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>
  }
}
Enter fullscreen mode Exit fullscreen mode

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

  ...
}
Enter fullscreen mode Exit fullscreen mode

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>
  ....
Enter fullscreen mode Exit fullscreen mode

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 }
  }
...
Enter fullscreen mode Exit fullscreen mode

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>
  }
}
Enter fullscreen mode Exit fullscreen mode

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)