DEV Community

React to Elm Migration Guide

Jesse Warden on April 25, 2021

This guide will help you learn and migrate to Elm with assumption you already know the basics of React. The Elm guide is great and will give you ...
Collapse
 
layflags profile image
Lay Flags

Thank you for this nice post Jesse! 🙏

BTW: In the JS example for "pattern matching" the break statements are missing.

Collapse
 
jesterxl profile image
Jesse Warden

I'm a moron, they're supposed to be return, whoops, thanks!

Collapse
 
layflags profile image
Lay Flags • Edited

True, returns are more appropriate :)

Collapse
 
johnkazer profile image
John Kazer

Any views on the differences between them regarding app scalability or shareability of components?

Collapse
 
jesterxl profile image
Jesse Warden • Edited

I'm going to answer your shareability separately because my experiences here may be unique and not applicable to many.

I'm a developer. I've never been good at CSS, and I don't plan on getting much better. This means I use a lot of component & CSS frameworks. Examples include Bulma & Bootstrap for personal work. For professional work, almost every large company I've worked at recently has 1 to many design systems. This means there are teams dedicated to working on both the atoms, colors, components, documentation, and tooling. Some are focused on React or Angular, while others target all. Some recently even have Lit or other Web Component support, doing their best to be framework agnostic.

So this provides some new challenges. How do you approach building components in Elm, then? This is a complicated, and nuanced area.

Typically, you'll use Elm.

There is a rise recently in kids loving elm-ui, but that reminds me of the days of Flash developers ignoring the tidal wave of CSS coming, so I ignore it.

I love elm-css so you can use the compiler to ensure your CSS is correct, but first off, why am I writing a lot of CSS with a design system, and second, I'm not smart enough to leverage it yet.

Third, there is some growth process that many Elm devs seem to want to create encapsulated components, so utilize Html.map so they can have their own update, model, etc. This is frowned upon in the Elm community, but some dig it?

Lastly, I've seen some success putting an Elm API on top of already built Web Components, specifically the Material Design ones. This cat wrote an Elm API on top of the MDC web components. This means you get to use raw JavaScript classes with guaranteed compile time types. This is NOT trivial work, either. I've used multiple versions of these, and seen how the author has changed the API over time to be more "Elm like" and easier to use. While I respect it, it makes me wonder if it's better to just code everything in Elm, but... I'm not sure. I'd have to build my own component library to know. Based on reading some of the source code of many web components, it seems a lot of the work is in CSS land, so perhaps this is a viable approach for Enterprises who already have many design systems.

In terms of share ability, :: shrugs ::. Most components are just functions. Some functions are easy to share if you already have the ability to make the inputs. However, if your components require specific types, then those need to be easy to create as well. So nothing unique here; same challenges you'd have in TypeScript of "creating re-usable code".

As a surviving ex-Flash & Flex developer, my gut says writing API's atop Web components is probably prudent for the long term of obeying web standards which always win and ensuring your Elm components will work in newer versions of Elm.

Collapse
 
jesterxl profile image
Jesse Warden • Edited

If you're just using React + JavaScript and raw Elm, both seem to be same. I like how both compile pretty fast at high Lines of Code. TypeScript gets really slow with a lot of code.

What I don't like is when JavaScript grows, it gets really dangerous to make changes. However, this then requires a lot of unit tests. Not just code tests, but possibly a variety. These are painful to maintain, and hard to get right. Using something like Jest isn't great because it's slow, and swallows your console log statements. Using Mocha is really nice, especially 8 which concurrency there is much easier to use. Problem with that is you're breaking from create-react-app norms, and that has a huge development and maintenance cost. Adding TypeScript can help a lot here.

It's also easy to allow juniors to play, but hard to provide guardrails. They may create larger than needed components. Generally that's ok, until that component becomes the cornerstone of your application. Unless they learn how to create public API's early, it becomes hard to safely refactor, or test some of this code. I've had the same problem in Angular 1 and 2.x.

Redux can become verbose, but manageable. The issue there, is unless your team understands pure functions, many have no idea why they're using Redux and would just rather use Context. The defeats the whole purpose of using a state management, but I acknowledge Context is a lot easier to grok for many. Pretty soon you have these "Context Pole Stakes" that are firmly rooted, and you can't easily move. You can work around, no doubt, but once you use more than 2 it can be frustrating. Combine this with both classes and Hooks calling for encapsulation "except for Context", for larger apps, you just have to learn how they work before you're productive.

Elm doesn't have any of these problems. It does have 4 new ones, though.

First, race conditions. Since there are no side effects, occasionally you'll get race conditions. Many developers do not understand how to handle multiple HTTP calls, say, wired up to a button in Elm or React. Do you always take the first? The last? Accept all? Does the visual design handle this? Those questions are often not asked, and you get weird bugs that only manifest in manual or smoke tests. This is why I'm pretty bullish on Cypress in both React and Elm because it can sus these out, quickly. The same happens when you start "obeying the URL" when implementing routing. A bit easier to debug this in Elm vs. React, but still wracks your mind. Bottom line, distributed architectures are hard on the front-end, too 😁!

The second problem is modeling the above. There are some interesting patterns that the Elm compiler can just type to "not make them a problem anymore". While awesome, this a skill, and the articles on it are few or academic. They don't need to be; simple patterns do exist, but you have to learn and practice. Not just async, but anything. This is a challenge for both new and experienced developers. Documenting this so others can understand it takes practice, too.

Third, ports are dangerous. Usually developers who are coding Elm already write pretty Functional and safe JavaScript, but still, you need to be super wary here. The best approach is to use Maybes even if you're bullish on Optional Chaining or Lodash getOr / Ramda props in JavaScript and secondly, liberally use try/catch.

Fourth, Functional Programming is harder than Imperative and Object Oriented Programming. Elm has thrown out the insane parts like Category Theory and Monad side effects, making it much more approachable, fun, and a valuable problem solving tool. Still, this learning curve is not to be underestimated. Functional Programming by its current employable nature is a lonely endeavor, and having a team learn together is better.

Collapse
 
jesterxl profile image
Jesse Warden

Oh, one last note on sharing. I did successfully demo going the other way, and using Elm to build components for a React app. Much easier for people to swallow bringing in a new framework with a super easy escape hatch. I'm still unclear on the best CICD approach but keeping in the monorepo with it seems best approach for now.

Collapse
 
_gdelgado profile image
Gio

Great write-up!

Collapse
 
alfredosalzillo profile image
Alfredo Salzillo

The quotes used in the single quote and template string comparation between js and elm are wrong

Collapse
 
jesterxl profile image
Jesse Warden • Edited

Dev.to's handling of quote, single quote, and template string quote in tables are pretty horrendous. I'm about to give up and just put on it's own lines.

Collapse
 
csaltos profile image
Carlos Saltos

Great !! ... thank for sharing !! 👍😎