React to Elm Migration Guide
Tags: elm, react, javascript, migration
Published: 2021-04-25 20:35:16


---
title: React to Elm Migration Guide 
published: true
description: This guide will help you learn and migrate to Elm with assumption you already know the basics of React.
tags: Elm,React,JavaScript,migration
canonical_url: https://jessewarden.com/2021/04/react-to-elm-migration-guide.html
cover_image: 
---

<a name="top"></a>

This guide will help you learn and migrate to Elm with assumption you already know the basics of React. The [Elm guide](https://guide.elm-lang.org/) is great and will give you a thorough understanding of everything you need to know, in a good order.

This guide is different. Instead, we’re going to start with the fundamentals of JavaScript & [React](https://reactjs.org/docs/hello-world.html), and how you’d do the equivalent, if any, in Elm. If you already know React, we’ll use those firm groundings so you can feel more comfortable understanding “what Elm means” when they say something using language and concepts familiar to React developers.

Contents
--------

- [What is React?](#whatisreact)
- [What is Elm?](#whatiselm)
- JavaScript and Elm Language Types
  - [Literals](#literals)
  - [Objects / Records](#objects)
  - [Functions](#functions)
  - [Control Flow](#controlflow)
  - [Strings](#strings)
  - [Nulls and Errors](#nullsanderrors)
  - [Function Composition](#functioncomposition)
  - [Pattern Matching](#patternmatching)
- [Hello World React](#helloworldreact)
- [Hello World Elm](#helloworldelm)
- [DOM Templates](#domtemplates)
- [Components](#components)
- [Event Handling](#eventhandling)
- [Event Handling With State](#eventhandlingwithstate)
- [Conditional Rendering](#conditionalrendering)
- [Lists](#lists)
- [Basic List Component](#basiclistcomponent)
- [Forms: Controlled Component](#formscontrolledcomponent)
- Thinking In React
  - [Mock](#thinkinginreactmock)
  - [Component Hierarchy](#thinkinginreactcomponenthierarchy)
  - [Represent UI State](#thinkinginreactrepresentuistate)
  - [Determine Where State Lives](#thinkinginreactdeterminewherestatelives)
- Thinking in Elm
  - [Model Data](#thinkinginelmmodeldata)
  - [Component Hierarchy](#thinkinginelmcomponenthierarchy)
  - [Model Data Changes](#thinkinginelmmodeldatachanges)
  - [Handle Events](#thinkinginelmmodelhandlevents)
- [Development](#development)
- [Testing](#testing)
- [Routing](#routing)
- [Error Boundaries](#errorboundaries)
- [HTTP](#http)
- [State Management](#statemanagement)

<a name="whatisreact"></a>What is React?
--------------

React is a library for ensuring your DOM is in sync with your data. However, one could argue it’s a framework in that it provides many fundamentals needed to build applications. There is enough features that you can adopt, that it is a sliding scale. Just want JSX and variables? Cool. Want a Context to emulate Redux? Cool. Want to swap out the render for something like [Preact](https://preactjs.com/)? Cool.

Modular to add and swap out parts with large community support to modify it to suit your needs.

It’s assumed you can write React in JavaScript. There are [basic runtime typings](https://reactjs.org/docs/typechecking-with-proptypes.html) enforced for component properties built into React. If you want something more, [TypeScript](https://www.typescriptlang.org/) support has been added as well.

A popular project, [create-react-app](https://reactjs.org/docs/create-a-new-react-app.html), rose in popularity because of it’s ability to handle the compiler toolchain for you. Teams do not have to know about Webpack or JavaScript build targets such as CommonJS, ES6, or ES5. While they don’t have to maintain the core, for cyber security findings or build reasons, you/the team will still have to upgrade more than you might want to. Out of the box you get a simple development environment with the ability to save a file and see it live reload. Tests are setup and ready to go. Finally, a production build with all kinds of optimizations are there. Having 3 simple basic commands of start, test, and build give you all you need to build most apps.

While you can utilize [npm](https://www.npmjs.com/), [yarn](https://yarnpkg.com/) is supported for those who want additional features that yarn provides.

[Top](#top)

<a name="whatiselm"></a>What is Elm?
------------

Elm is a strongly typed functional language, compiler, package manager, and framework. You write in the Elm language, and it compiles to JavaScript for use in the browser. The Elm compiler has 2 basic modes of development, and production. It optionally has a REPL if you want to test some basic code. The package manager uses it’s [own website](https://package.elm-lang.org/) and structure using elm.json, instead of package.json. The framework is what Elm is most known for, and was the inspiration for [Redux](https://redux.js.org/).

You code in Elm, in the Elm framework, install Elm libraries, and compile using the Elm compiler, into JavaScript. Most learning apps will compile to an HTML page which includes the JavaScript and CSS automatically. For more commonly advanced applications, you’ll just compile to JavaScript and embed in your own index.html. This often works better when you want to do additional HTML and CSS things to the main HTML file. There is a create-elm-app but it tends to violate the Elm philosophy of not using complex, hard to maintain JavaScript build tool-chains.

<a name="javascriptandelmlanguage"></a>JavaScript and Elm Language Types
---------------------------------

The following tables compare the basics of JavaScript to Elm.

[Top](#top)

<a name="literals"></a>
### Literals

|                   JavaScript                   	|                  Elm                 	|
|:----------------------------------------------:	|:------------------------------------:	|
| `3`                                              	| `3`                                    	|
| `3.125`                                          	| `3.125`                                	|
| `"Hello World!"`                                 	| `"Hello World!"`                       	|
| `'Hello World!'`                                 	| cannot use single quotes for strings 	|
| `'Multiline string.'` (backtick, not ')                            	| `"""Multiline string"""`               	|
| No distinction between characters and strings. 	| `'a'`                                  	|
| `true`                                           	| `True`                                 	|
| `[1, 2, 3]`                                      	| `[1, 2, 3]`                            	|


[Top](#top)

<a name="objects"></a>
### Objects / Records

|   JavaScript   	|         Elm         	|
|:--------------:	|:-------------------:	|
| { x: 3, y: 4 } 	| { x = 3, y = 4 }    	|
| point.x        	| point.x             	|
| point.x = 42   	| { point &#124; x = 42 } 	|

[Top](#top)

<a name="functions"></a>
### Functions

|            JavaScript           	|          Elm          	|
|:-------------------------------:	|:---------------------:	|
| `function(x, y) { return x + y }` 	| `\x y -> x + y`         	|
| `Math.max(3, 4)`                  	| `max 3 4`               	|
| `Math.min(1, Math.pow(2, 4))`     	| `min 1 (2^4)`           	|
| `numbers.map(Math.sqrt)`          	| `List.map sqrt numbers` 	|
| `points.map( p => p.x )`          	| `List.map .x points`    	|

[Top](#top)

<a name="controlflow"></a>
### Control Flow

|       JavaScript      	|                       Elm                       	|
|:---------------------:	|:-----------------------------------------------:	|
| `3 > 2 ? 'cat' : 'dog'` 	| `if 3 > 2 then "cat" else "dog"`                  	|
| `var x = 42; ...`       	| `let x = 42 in ...`                               	|
| `return 42`             	| Everything is an expression, no need for `return` 	|

[Top](#top)

<a name="strings"></a>
### String

|      JavaScript     	|             Elm             	|
|:-------------------:	|:---------------------------:	|
| `'abc' + '123'`       	| `"abc" ++ "123"`              	|
| `'abc'.length`        	| `String.length "abc"`         	|
| `'abc'.toUpperCase()` 	| `String.toUpper "abc"`        	|
| `'abc' + 123`         	| `"abc" ++ String.fromInt 123` 	|

[Top](#top)

<a name="nullsanderrors"></a>
### Nulls and Errors

|        JavaScript        	|        Elm        	|
|:------------------------:	|:-----------------:	|
| `undefined`                	| `Maybe.Nothing`     	|
| `null`                     	| `Maybe.Nothing`     	|
| `42`                       	| `Maybe.Just 42`     	|
| `throw new Error("b00m")`  	| `Result.Err "b00m"` 	|
| `42`                       	| `Result.Ok 42`      	|

[Top](#top)

#### JavaScript

You’ll often see JavaScript to emulate the above using [Optional Chaining](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining).

```javascript
// has a value
const person = { age: 42 }
const age = person?.age

// is undefined
const person = { }
const age = person?.age
```


#### Elm

```elm
type alias Person = { age : Maybe Int }
-- has a value
let person = Person { age = Just 42 }
-- is nothing
let person = Person { age = Nothing }
```


<a name="functioncomposition"></a>
### Function Composition (i.e. “Pipelines”)

Both languages below parse the following JSON String to get human names in a list.

[Top](https://jessewarden.com/wp-admin/post.php?post=6208&action=edit#top)

#### JavaScript

The [JavaScript Pipeline Operator proposal is at stage 1](https://github.com/tc39/proposal-pipeline-operator) at the time of this writing, so we’ll use a Promise below.

```javascript
const isHuman = peep => peep.type === 'Human'
const formatName = ({ firstName, lastName }) => `${firstName} ${lastName}`

const parseNames = json =>
  Promise.resolve(json)
  .then( JSON.parse )
  .then( peeps => peeps.filter( isHuman ) )
  .then( humans => humans.map( formatName ) ) 
```


#### Elm

```elm
isHuman peep =
  peep.type == "Human"

formatName {firstName, lastName} =
  firstName ++ " " ++ lastName

parseNames json =
  parseJSON
  |> Result.withDefault []
  |> List.filter isHuman
  |> List.map formatName
  
```


[Top](https://jessewarden.com/wp-admin/post.php?post=6208&action=edit#top)

<a name="patternmatching"></a>
### Pattern Matching

**JavaScript**

The [current pattern matching proposal for JavaScript is Stage 1](https://github.com/tc39/proposal-pattern-matching) at the time of this writing.

```javascript
switch(result.status) {
  case "file upload progress":
    return updateProgressBar(result.amount)
  case "file upload failed":
    return showError(result.error)
  case "file upload success":
    return showSuccess(result.fileName)
  default:
    return showError("Unknown error.")
}
```


**Elm**

```elm
case result.status of
  FileUploadProgress amount ->
    updateProgressBar amount
  FileUploadFailed err ->
    showError err
  FileUploadSuccess fileName ->
    showSuccess filename
  _ ->
    showError "Unknown error."
```


[Top](https://jessewarden.com/wp-admin/post.php?post=6208&action=edit#top)

<a name="helloworldreact"></a>Hello World: React
------------------

```react
ReactDOM.render(
  <h1>Hello, world!</h1>, document.getElementById('body')
)
```


<a name="helloworldelm"></a>Hello World: Elm
----------------

```elm
type Msg = Bruh
type alias Model = {}
 
update _ model =
    model

view _ =
    h1 [][ text "Hello World!" ]

main =
    Browser.sandbox
        { init = (\ () -> {})
        , view = view
        , update = update
        }

```


[Top](https://jessewarden.com/wp-admin/post.php?post=6208&action=edit#top)

<a name="domtemplates"></a>DOM Templates
-------------

### JSX Element

```react
const element = <h1>Hello world!</h1>;
```


### Elm Element

```elm
let element = h1 [] [text "Hello World!"]
```


### JSX Dynamic Data

```react
const name = 'Jesse';
<h1>Hello {name}</h1>
```


### Elm Dynamic Data

```elm
let name = "Jesse"
h1 [] [text "Hello " ++ name ]
```


### JSX Functions

```react
const format = ({ first, last }) => `${first} ${last}`;

const user = { first: 'Jesse', last: 'Warden' };

<h1>Hello {format(user)}</h1>
```


### Elm Functions

```elm
format {first, last} = first ++ " " ++ last

user = { first = "Jesse", last = "Warden" }

h1 [] [text (format user) ] 
```


### JSX Image

```react
<img src={user.avatarUrl} />
```


### Elm Image

```elm
img [ src user.avatarUrl ] []
```


JSX Children

```react
const element = (
  <div>
    <h1>Hello!</h1>
    <h2>Good to see you here.</h2>
  </div>
);
```


### Elm Children

```elm
let element =
  div [] [
    h1 [] [text "Hello!"]
    h2 [] [text "Good to see you here."]
  ]
```


[Top](https://jessewarden.com/wp-admin/post.php?post=6208&action=edit#top)

<a name="components"></a>Components
----------

### React: Define

```react
const Welcome = props => <h1>Hello {props.name}</h1>
```

### Elm: Define

```elm
welcome props = h1 [] [text "Hello " ++ props.name]
```

### React: Use

```react
const element = <Welcome name="Sara" />
```

### Elm: Use

```elm
let element = welcome { name = "Sara" }
```

### React: Children

```react
const Greeting = ({ name }) => (
  <div>
    <h1>Hello!</h1>
    <h2>Good to see you here, {name}!</h2>
  </div>
)
```

### Elm: Children

```elm
greeting {name} =
  div [] [
    h1 [] [text "Hello!"]
    , h2 [] [text "Good to see you here, " ++ name ++ "!"]
  ]
```

[Top](#top)

<a name="eventhandling"></a>Event Handling
--------------

### React Event Handler

```react
<button onClick={activateLasers}>Activate Lasers</button>
```

### Elm Message

```elm
button [ onClick ActivateLasers ] [ text "Activate Lasers" ]
```

### React Event Parameter

```react
<button onClick={(e) => this.deleteRow(23, e)}>Delete Row</button>
```

### Elm Message Parameter

```elm
type Msg = DeleteRow Int

button [ onClick (DeleteRow 23) ] [ text "Delete Row" ]
```

[Top](#top)

<a name="eventhandlingwithstate"></a>Event Handling With State
-------------------------

### React

```react
class Toggle extends React.Component {
  constructor(props) {
    super(props);
    this.state = {isToggleOn: true};
  }
  
  handleClick = () => {
    this.setState(state => ({ isToggleOn: !state.isToggleOn }));
  }
  
  render = () => (
      {this.state.isToggleOn ? 'ON' : 'OFF'}
    )
  }
}
```


### Elm

```elm
type alias Model = { isToggleOn : Bool }

initialModel = { isToggleOn = True }

type Msg = Toggle

update _ model =
  { model | isToggleOn = not model.isToggleOn }

toggle model =
    div 
      [ onClick Toggle ]
      [ if model.isToggleOn then
          text "ON"
        else
          text "OFF" ]
```


[Top](https://jessewarden.com/wp-admin/post.php?post=6208&action=edit#top)

<a name="conditionalrendering"></a>Conditional Rendering
---------------------

### React

```react
function Greeting(props) {
  const isLoggedIn = props.isLoggedIn;
  if (isLoggedIn) {
    return <UserGreeting />;
  }
  return <GuestGreeting />;
}
```


### Elm

```elm
greeting props =
  let
    isLoggedIn = props.isLoggedIn
  in
  if isLoggedIn then
    userGreeting()
  else
    guestGreeting()
```


[Top](https://jessewarden.com/wp-admin/post.php?post=6208&action=edit#top)

<a name="lists"></a>Lists
-----

### React

```react
const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number) =>
  <li>{number}</li>
);
```


### Elm

```elm
let numbers = [1, 2, 3, 4, 5]
let listItems =
  List.map
    (\number -> li [] [text (String.fromInt number)])
    numbers
```


[Top](https://jessewarden.com/wp-admin/post.php?post=6208&action=edit#top)

<a name="basiclistcomponent"></a>Basic List Component
--------------------

### React

```react
function NumberList(props) {
  const numbers = props.numbers;
  const listItems = numbers.map((number) =>    <li>{number}</li>  );
  return (
    <ul>{listItems}</ul>
  );
}

const numbers = [1, 2, 3, 4, 5];
<NumberList numbers={numbers} />
```


### Elm

```elm
numberList props =
  let
    numbers = props.numbers
  in
  List.map
    (\number -> li [] [text (String.fromInt number)])
    numbers

let numbers = [1, 2, 3, 4, 5]
numberList numbers
```


[Top](https://jessewarden.com/wp-admin/post.php?post=6208&action=edit#top)

<a name="formscontrolledcomponent"></a>Forms: Controlled Component
---------------------------

### React

```react
class NameForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {value: ''};
  }

  handleChange = event => {
    this.setState({value: event.target.value});
  }
  
  handleSubmit = event => {
    alert('A name was submitted: ' + this.state.value);
    event.preventDefault();
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          Name:
          <input type="text" value={this.state.value} onChange={this.handleChange} />
        </label>
        <input type="submit" value="Submit" />
      </form>
    );
  }
}
```


### Elm

```elm
type Msg = TextChanged String | Submit

type alias Model = { value : String }

initialModel = { value = "" }
 
update msg model =
    case msg of
        TextChanged string ->
            { model | value = string }
        Submit ->
            let
                _ = Debug.log "A name was submitted: " model.value
            in
            model

view model =
    form [ onSubmit Submit ][
        label
            []
            [ text "Name:"
            , input
              [type_ "text", value model.value, onInput TextChanged ] []]
        , input [type_ "submit", value "Submit"][]
    ]
```


[Top](https://jessewarden.com/wp-admin/post.php?post=6208&action=edit#top)

<a name="thinkingin"></a>Thinking In
-----------

### React

React’s always been about the ease of creating components, then composing those components together into an application. Look at a UI, see the seams in your mind, and decide who will manage the various pieces of state.

1. Mock
2. Component Hierarchy
3. Represent UI State
4. Determine Where State Lives

<a name="thinkinginreactmock"></a>
#### 1 – Mock Data

In React, you’ll mock the data you get from the potential back-end API or[ back-end for front-end](https://samnewman.io/patterns/architectural/bff/) that you’ll build. Below, we hard code some mock JSON so our components can show something and we can visually design & code around this data:

```react
[
  {category: "Sporting Goods", price: "$49.99", stocked: true, name: "Football"},
  {category: "Sporting Goods", price: "$9.99", stocked: true, name: "Baseball"},
  {category: "Sporting Goods", price: "$29.99", stocked: false, name: "Basketball"},
  {category: "Electronics", price: "$99.99", stocked: true, name: "iPod Touch"},
  {category: "Electronics", price: "$399.99", stocked: false, name: "iPhone 5"},
  {category: "Electronics", price: "$199.99", stocked: true, name: "Nexus 7"}
];
```


<a name="thinkinginreactcomponenthierarchy"></a>
#### 2 – Component Hierarchy

Next, you’ll either create components from that data that you’ll represent, and see how each is a component with it’s own ability to represent the data visually and possibly handle user input… or do the same to a design comp given to you by a designer. Whether that’s the small components in the tree, or the bigger ones who bring it all together; that’s up to you.

![](https://jessewarden.com/wp-content/uploads/2021/04/thinking-in-react-mock.png)Typically you’ll either eyeball the data and the components will start to visualize in your mind, OR you’ll see the design comp and start to slice the various parts into a component tree in your head.

![](https://jessewarden.com/wp-content/uploads/2021/04/thinking-in-react-components.png)1. **`FilterableProductTable` (orange):** brings all components together
2. **`SearchBar` (blue):** receives all *user input*
3. **`ProductTable` (green):** displays and filters the *data collection* based on *user input*
4. **`ProductCategoryRow` (turquoise):** displays a heading for each *category*
5. **`ProductRow` (red):** displays a row for each *product*

<a name="thinkinginreactrepresentuistate"></a>
#### 3 – Represent UI State

Third, you’ll think strongly about state if you didn’t “figure out out” going through Step 2. Most data can be props, but if a component is controlled, perhaps it may have it’s own state that would help it interact with other components? Favor props, but use state where you need to encapsulate it into components. Whether using an Object Oriented class based approach, or a Functional one, often components will contain things you feel it’s best for them to manage internally.

<a name="thinkinginreactdeterminewherestatelives"></a>
#### 4 – Determine Where State Lives

Lastly, identify who owns the source of truth. While many components can have their own internal state, the “state of the app” is typically owned by one or a select few. The interactions between these components will help you sus out where it should probably live, and how you’ll manage it (events, Context, Hooks, Redux, etc).

[Top](https://jessewarden.com/wp-admin/post.php?post=6208&action=edit#top)

### Elm

While many, myself included, wish to immediately jump to building components, Elm encourages thinking hard about your Model first. Elm’s types allow you to make [impossible application states impossible](https://www.youtube.com/watch?v=IcgmSRJHu_8), and simplifying how you represent things. The good news, if you screw this up, the Elm compiler has the best error messages in the industry and allows you to refactor without fear.

1. Model Data
2. Component Hierarchy
3. Model Data Changes
4. Handle Events

<a name="thinkinginelmmodeldata"></a>
#### 1 – Model Data

Step 1 is to model your data using Elm’s type system. Like React, some will either be dictated like an API, or it’s something you can customize from a BFF. However, this can be heavily influenced by your Designer’s comp as well.

```elm
type alias Product = {
  category : String
  , price : String
  , stocked : Bool
  , name : String }

type alias Model = {
  products : List Product
}

initialModel =
[
  Product {category = "Sporting Goods", price = "$49.99", stocked = True, name = "Football"}
  , Product {category = "Sporting Goods", price = "$9.99", stocked = True, name = "Baseball"}
  , Product {category = "Sporting Goods", price = "$29.99", stocked = False, name = "Basketball"}
  , Product {category = "Electronics", price = "$99.99", stocked = True, name = "iPod Touch"}
  , Product {category = "Electronics", price = "$399.99", stocked = False, name = "iPhone 5"}
  , Product {category = "Electronics", price = "$199.99", stocked = True, name = "Nexus 7"}
]
```


<a name="thinkinginelmcomponenthierarchy"></a>
#### 2 – Component Hierarchy

Almost the exact same as React, except there is no state in components; all state is your Model. Your `FilterableProductTable`, `SearchBar`, etc. are just functions that often take in the model as the first and only parameter.

<a name="thinkinginelmmodeldatachanges"></a>
#### 3 – Model Data Changes

Even if you use Redux in React, you still reserve the right to occasionally keep internal component state. Not so in Elm; all state is in your model. That means your `SearchBar (blue)` would have a `currentFilter : String` on your model to capture what the current filter, if any, exists. You’d also have a `onlyInStock : Bool` for the checkbox. In React, both of those could be:

- state in the component via `this.state`
- state in the component via `FilterableProductTable` that you’d pass up via events
- state in Redux
- state in a Hook
- state in a shared Context

In Elm, there is no question where: it’s in the model.

<a name="thinkinginelmmodelhandlevents"></a>
#### 4 – Model Event Changes

In Elm, you do not need to decide “where UI state lives” because… all data lives in the Model. Instead, you need to decide how to change that data. For simple applications, it’s much like you’d do in Redux: create a Message containing the new data, and write code to change your model based on that message.

```elm
type Msg = ToggleOnlyInStock Bool
```


Now that you have your message, you’ll dispatch it when the user clicks the checkbox:

```elm
label
        [ ]
        [ input [ type_ "checkbox", onClick (ToggleOnlyInStock not model.onlyInStock) ] []
        , text "Only show products in stock"]
```


Lastly, change the data based on the message:

```elm
update msg model =
  ...
  ToggleOnlyInStock toggle ->
    { model | onlyInStock = toggle }
```


[Top](https://jessewarden.com/wp-admin/post.php?post=6208&action=edit#top)

<a name="development"></a>Development
-----------

### React

Using [create-react-app](https://reactjs.org/docs/create-a-new-react-app.html), you’ll run `npm start` and your changes + compile errors will be reflected quickly in the open browser window.

For a production build, run `npm run build`.

### Elm

Using [elm-live](https://github.com/wking-io/elm-live), you’ll run elm-live and your changes + compile errors will be reflected quickly in the open browser window.

For a production build, run `elm make` with the `--optimize` flag. It’s recommended you additionally utilize [uglifyjs](https://github.com/mishoo/UglifyJS) first with compress then again with mangle, or some other compressor + mangler library.

[Top](https://jessewarden.com/wp-admin/post.php?post=6208&action=edit#top)

<a name="testing"></a>Testing
-------

### React

Using create-react-app, you’ll run `npm test` which uses [Jest](https://jestjs.io/) internally. If you are dealing with a lot of data on the UI, or using [TypeScript](https://www.typescriptlang.org/), use [JSVerify](https://github.com/jsverify/jsverify) for property tests. For end to end tests, [Cypress](https://www.cypress.io/) is a great choice.

Elm
---

For Elm, unit tests often do not provide value given the compiler’s correctness. They’re better expressed using end to end tests and those are more likely to expose your race conditions. If you are dealing with a lot of data on the UI, use [elm-test](https://package.elm-lang.org/packages/elm-explorations/test/latest/) for property tests. While normally for unit-tests, it has fuzzers and shrinkers built in. For end to end tests, Cypress is a great choice.

[Top](https://jessewarden.com/wp-admin/post.php?post=6208&action=edit#top)

<a name="routing"></a>Routing
-------

### React

While there are a variety of choices, [react-router](https://reactrouter.com/) is one many settle on.

```react
function Home() {
  return <h2>Home</h2>;
}

function About() {
  return <h2>About</h2>;
}

function Users() {
  return <h2>Users</h2>;
}

function App() {
  return (
    <Router>
      <div>
        <nav>
          <ul>
            <li>
              <Link to="/">Home</Link>
            </li>
            <li>
              <Link to="/about">About</Link>
            </li>
            <li>
              <Link to="/users">Users</Link>
            </li>
          </ul>
        </nav>
      </div>
    </Router>
  )
}
```


### Elm

Elm has routing [built-in](https://package.elm-lang.org/packages/elm/browser/latest/Browser-Navigation) using the [Browser library](https://package.elm-lang.org/packages/elm/browser/latest/Browser-Navigation).

```elm
home =
  h2 [] [ text "Home" ]

about =
  h2 [] [ text "About" ]

users =
  h2 [] [ text "Users" ]

app =
  div [] [
    nav [] [
      ul [] [
        li [] [
          a [ href "/home" ] [ text "Home" ]
        ]
        , li [] [
          a [ href "/about" ] [ text "About" ]
        ]
        , li [] [
          a [ href "/users" ] [ text "Users" ]
        ]
      ]
    ]
  ]

```


[Top](https://jessewarden.com/wp-admin/post.php?post=6208&action=edit#top)

<a name="errorboundaries"></a>Error Boundaries
----------------

### React

In React, you’ll build a component, or set of components, to wrap common error areas so in case a volatile part of the UI throws, you can handle it gracefully in the UI. First create a basic wrapper component:

```react
class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }

  static getDerivedStateFromError(error) {
    // Update state so the next render will show the fallback UI.    return { hasError: true };
  }

  componentDidCatch(error, errorInfo) {
    // You can also log the error to an error reporting service
    logErrorToMyService(error, errorInfo);
  }

  render() {
    if (this.state.hasError) {
      // You can render any custom fallback UI
      return <h1>Something went wrong.</h1>;
    }
    return this.props.children; 
  }
}
```


Once you’ve got your component with logging and a fallback UI, you just wrap the dangerous components:

```react
<ErrorBoundary>
  <MyWidget />
</ErrorBoundary>
```


### Elm

Elm does not have runtime errors (caveat: port dangers in section down below). The compiler will ensure that all possible errors are handled. This means you either model those error states in your model, ignore them with blank strings, or design different UI’s for those states.

Data not there? You must handle it:

```elm
case dataMaybe of
  Just data ->
    addProduct data
  Nothing ->
    -- Your UI or data must compensate somehow here.
    -- For now we just return all the products unchanged
    model.products
```


HTTP operation you need to work fail? You must handle it:

```elm
case result of
  Error err ->
    { model | result = ProductSaveFailed err }
  Ok data ->
    { mdoel | result = ProductSaveSuccess data }

-- in UI
case result of
  ProductSaveFailed err ->
    errorViewAndRetry err
  ProductSaveSuccess _ ->
    goToProductView
```


[Top](https://jessewarden.com/wp-admin/post.php?post=6208&action=edit#top)

<a name="http"></a>HTTP
----

### React

```react
class Weather extends React.Component {
  constructor(props) {
    super(props);
    this.state = { temperature: undefined, loading: true };
  }

  componentDidMount = () => {
    this.setState({ loading: true })
    fetch("server.com/weather/temperature")
    .then( response => response.json() )
    .then( 
       ({ temperature }) => {
         this.setState({ temperature, loading: false, isError: false }) )
      }
    )
    .catch(
      error => {
        this.setState({ loading: false, isError: true, error: error.message })
      }
    )
  }

  render() {
    if(this.state.loading) {
      return <p>Loading...</p>
    } else if(this.state.isError === false) {
      return <p>Temperature: {this.state.temperature}</p>
    } else {
      return <p>Error: {this.state.error}</p>
    }
  }
}
```


### Elm

```elm
type Msg = LoadWeather | GotWeather (Result Http.Error String)

type Model
    = Loading
    | Success String
    | Failure Http.Error

init : () -> (Model, Cmd Msg)
init _ =
  ( Loading
  , loadTemperature
  )
 
loadTemperature =
    Http.get
      { url = "server.com/weather/temperature"
      , expect = Http.expectJson GotWeather temperatureDecoder
      }
    
temperatureDecoder =
  field "temperature" string

update msg model =
    case msg of
        LoadWeather ->
            (Loading, loadTemperature)
        GotWeather result ->
            case result of
                Err err ->
                    ( Failure err, Cmd.none )
                Ok temperature ->
                    ( Success temperature, Cmd.none )

view model =
    case model of
        Loading ->
            p [][text "Loading..."]
        Success temperature ->
            p [][text ("Temperature: " ++ temperature) ]
        Failure _ ->
            p [][text "Failed to load temperature."]
```


[Top](https://jessewarden.com/wp-admin/post.php?post=6208&action=edit#top)

<a name="statemanagement"></a>State Management
----------------

### Redux

```react
// Action Creator
const addTodo = text => ({ type: 'ADD_TODO', text })

// Dispatch
const goSwimming = () => store.dispatch(addTodo('Go Swimming.'))

// trigger from button
<button onClick={goSwimming}>Add</button>

// update model
const todos = (state = [], action) => {
  switch (action.type) {
    case 'ADD_TODO':
      return state.concat([{ text: action.text, completed: false }])
    default:
      return state
  }
}
```


### Elm

```elm
-- Type for Todo
type alias Todo = { text : String, completed: Bool }

-- Message
type Msg = AddTodo String

-- trigger from button
button [ onClick (AddTodo "Go Swimming.")] [ text "Add" ]

-- update model
update msg model =
  case msg of
    AddTodo text ->
      { model | todos = List.append model.todos [Todo text, False] }
    ...
```


[Top](https://jessewarden.com/wp-admin/post.php?post=6208&action=edit#top)