DEV Community

Risyad Rais Rafsanjani
Risyad Rais Rafsanjani

Posted on

The Elm Architecture with React

I was not interested in learning front-end development so much. Not really hated it. I just underestimated it so much that I think I'll learn it in an instant. Oh, boy. My arrogance bit me hard!

My front-end development journey was not so straightforward. From JQuery around 2014, I skipped all the way to _hyperscript (2023? Can't remember exactly). Then I started learning Rescript-react, Elm, exploring what's out there other than JS to build a front-end. Found Preact only to help me understand a bit more of React, and going back to Rescript-React only to rediscover Elm with the infamous The Elm Architecture. At this point, I'm still waiting for the next twist.

State management is a hell of a pain to dance around to. So I kind of jokingkly said to my learning partner (chatGPT lol). What if I do React, but do the state management like Elm? On top of Rescript? And boom. Everything's fallen to it's place. Reducer, ADTs, etc, etc. Now it's been weeks and I'm still having fun learning.

Imitating Elm

Imitating Elm to a TEA (got it?) using Rescript means you get the architecture and noisy compiler. And I'm in for it.

The architecture is simple. If I understand it correctly, the architecture is:

Model -> Update -> View
Enter fullscreen mode Exit fullscreen mode

The model is the state of the application. The update is the function that updates the model. The view changes matching the shape of the model (state).

Heh, I know. I'm bad at explaining so let's just jump into it. Read this snippet:

type model = {
    sub_1Model: Sub_1.model,
    sub_2Model: Sub_2.model,
    sub_3Model: Sub_3.model,
}

let init = (): model => {
  sub_1Model: Sub_1.init(),
  sub_2Model: Sub_2.init(),
  sub_3Model: Sub_3.init(),
}

type msg = 
    | Sub_1Msg(Sub_1.msg)
    | Sub_2Msg(Sub_2.msg)
    | Sub_3Msg(Sub_3.msg)

let update = (model: model, msg: msg): model =>
  switch msg {
      | Sub_1Msg(sub1msg) => {sub_1Model: Sub_1.update(sub1msg, model.sub_1Model)}
      | Sub_2Msg(sub2msg) => {sub_2Model: Sub_2.update(sub2msg, model.sub_2Model)}
      | Sub_3Msg(sub3msg) => {sub_3Model: Sub_3.update(sub3msg, model.sub_3Model)}
  }
Enter fullscreen mode Exit fullscreen mode

How'd that work under React, you asked?

  let (model, dispatch) = React.useReducer(update, init())
Enter fullscreen mode Exit fullscreen mode

Boom. Reducer, baby!

See! I'm really bad at explaining. I hope future me know how to make this make sense since I'm writing this for him.

Top comments (0)