Elm Language was specifically designed to build front-end applications, and it offers a great experience as a whole. Its most shiny features are:

  1. Great performance using the virtual DOM
  2. Functional language
  3. Safety through a Powerful type system
  4. State management using the built-in Elm architecture
  5. A powerful and helpful compiler

We will see how to achieve 3, 4 and 5 using React, Redux and Flow.

Let's look at some Elm code:

import Html exposing (Html, button, div, text)
import Html.Events exposing (onClick)

main =
  Html.beginnerProgram
    { model = model
    , view = view
    , update = update
    }

-- MODEL
type alias Model = Int

model : Model
model =
  0

-- UPDATE
type Msg
  = Increment
  | Decrement


update : Msg -> Model -> Model
update msg model =
  case msg of
    Increment ->
      model + 1

    Decrement ->
      model - 1

-- VIEW
view : Model -> Html Msg
view model =
  div []
    [ button [ onClick Decrement ] [ text "-" ]
    , div [] [ text (toString model) ]
    , button [ onClick Increment ] [ text "+" ]
    ]

https://gist.github.com/haikyuu/abd1145667e02aee2332d55e0d99bd33

The beauty of Elm is that every Elm app is written using the same parts:

The syntax is a bit weird for newcomers but it just takes some getting used to.

And its equivalent (commented) using React, Redux and Flow:

//@flow
import React from 'react';
import ReactDOM from 'react-dom';
import { createStore, bindActionCreators } from 'redux'
import { Provider, connect } from 'react-redux'

type Increment = {
  type: "INCREMENT"
}
type Decrement = {
  type: "DECREMENT"
}
type CounterActions =
  | Increment
  | Decrement

type Action = CounterActions // whenever we add a reducer, we add its actions here

//make sure dispatch can only dispatch our predefined actions
//and returns the action dispatched
type domainIdentity<T> = <A: T>(a: A) => A
type Dispatch = domainIdentity<Action>


type CounterState = number

//reducer
const counter = (state: CounterState = 0, action: CounterActions) =>{
  switch (action.type) {
    case 'INCREMENT':
      return state + 1
    case 'DECREMENT':
      return state - 1
    default:
      (action: empty); //to make sure we handle all the actions
      //it will trigger a flow error when we forget a case !!
      return state
  }
}

//action creators
const increment = (): Increment => ({ type: "INCREMENT" })
const decrement = (): Decrement => ({ type: "DECREMENT" })

// our global state, also needs to be modified whenever we add a reducer
type State = CounterState

// passing state to our component as props
const mapStateToProps = (state: State) => ({state})

const mapDispatchToProps = (dispatch: Dispatch) => bindActionCreators({
  increment,
  decrement,
}, dispatch)


//helper flow types .. should be in a config file
type _ExtractReturn<B, F: (...args: any[]) => B> = B;
/*export*/ type ExtractReturn<F> = _ExtractReturn<*, F>;

//redux state and action creators types
type ReduxProps = ExtractReturn<typeof mapStateToProps>;
type ReduxActions = ExtractReturn<typeof mapDispatchToProps>;

//View
//we don't have any props except redux ones
type Props = {} & ReduxProps & ReduxActions
const App = ({ decrement, increment, state }: Props) =>(
  <div>
    <button onClick={decrement}>-</button>
    <div>{state}</div>
    <button onClick={increment}>+</button>
  </div>
)
//connect our component with the redux store
const ConnectedApp = connect(mapStateToProps, mapDispatchToProps)(App)

let store = createStore(counter)

ReactDOM.render(
  (<Provider store={store}>
      <ConnectedApp />
  </Provider>), document.getElementById('root')
);

https://gist.github.com/haikyuu/a540268b3336a52de69ae94d8e3b9e3c

A few things to note:

If you cannot use Elm in your day job, you can still benefit from similar goodies using Flow.

You will also become a better React developer by learning Elm, so check it out.

Alaoui Abdellah

React and React Native developer. Loves Flow and currently exploring OCaml and ReasonML. Curious and eager to learn.

  1. Comments for Achieve more with Less code, Elm vs React-Redux-Flow

You must login to comment

You May Also Like