Functional Programming in JavaScript with Hyperapp

I kinda feel like a traitor given my pretty long history with Vue and React, but I think I have a new go-to frontend framework. Hyperapp is everything that I wanted Elm to be -- it's easy to build code with, highly organized, and state is handled flawlessly. That being said, it's not as production ready as the aforementioned frameworks, but once it is I can see it being huge.

Let's start with zero on building a Hyperapp app -- with tools that are still emerging, I usually go more in-depth. I'll do the same here for Hyperapp.

Getting Started

A few weeks ago, I saw a few articles about Hyperapp when they released version 1.0 and surpassed 10,000 stars on GitHub. I looked briefly at the counter "hello world" in their documentation. I really liked how clean and simple it looked, and I wanted to try it out!

You can also use JSX instead of calling the h function to create elements. That's what I did since I am used to it from React! I looked through the examples on Hyperapp's Codepen. I ended up using a boilerplate so that I didn't have to setup webpack for transpiling JSX or have to deal with the setup. It was awesome, I didn't have any issues using it and it came with a file structure that I enjoyed using.

Hyperapp uses an architecture inspired by Elm's -- it has views, models, and updates. It also follows the functional philosophy, similar to Elm. That means that state is immutable and the actions don't have side effects. The state management felt more like Redux than standard React, since state is centralized rather than component specific. Also, you do have to use thunks in order to build impure functions. The architecture and setup was smooth to work with and I didn't have many problems with it at all.

Since I've worked with Elm, React, Redux, Vue and Vuex in the past, I recognized the patterns and felt fine moving on to the final project after reading the documentation (which is minimal) and looking at the code examples.

The Final Project

I wanted to build something that would pull from an API -- which can be a relatively messy process in Redux. I didn't have one in mind, so I browsed this list to try and find one. I ended up using the FavQs API -- I had an idea to make a rotating list of quotes with a search available for the tags on different quotes. This would allow me to interact with the state quite a bit.

The first code that I wrote was the model for the state. I set initial properties for the attributes I needed in my project:

exportdefault{quotes:[],term:'',index:0}

Here, something like TypeScript or Flow would have been nice to enforce typing. I'm sure they could be integrated easily enough into a hyperapp project.

The quotes were an array of the quotes coming back from the API, the term was the search term if the user specified that, and then the index was the current index of the quote the user was looking at.

I used thunks for getQuotes and submitSearch -- meaning that I just actions a function from a function rather than a value. This allows for impure functions within the nested function, especially since the data from APIs is less predictable than functional programming requires. Since the Axios requests take a bit to execute, the state isn't actually updated until the setQuotes method is called after the data is fetched from the API. The other actions are relatively straight forward! The event handlers do take the event first and then the current state afterwards -- I did find this a bit "magic-y" but overall the experience with the actions was very smooth.

It looks essentially identical to a functional component in React! The event handlers are lower case, but otherwise the JSX is the same. Lifecycle methods are also a little bit different. I would normally use componentDidMount method in React to make an API request, but here I used the oncreate attribute instead. They do essentially the same thing, but the syntax is different. I also didn't see documentation for subscriptions, which are important in Elm. They allow you to use Websockets and add global event listeners. Some of the GitHub issues mentioned them, though, so I would assume they are implemented but not in the documentation yet.

This binding is essentially identical to how Elm combines the elements!

I liked splitting my code into multiple files, and I thought that it was really scalable. I could definitely see myself building something bigger with HyperApp in the future.

Next Steps

Again, Hyperapp is one of my favorite tools I've learned recently -- next to maybe Golang. I found it to be a nearly perfect marriage of tools that I've used in the past. It is also a tiny library and is super efficient, which is exciting especially in comparison to Angular, which I learned last week! Its API is so minimalistic and it enforces functional programming so well. I would definitely recommend learning it as an onramp to React with Redux. I would 100% use HyperApp again, I found it straightforward and I really liked the elegance of the code. I do hope that the community keeps expanding, the documentation improves, and a Redux/Elm like rewind feature is implemented. Otherwise, I had an excellent experience with Hyperapp and I am already planning on using it again!

Thanks for the great writeup! Definitely going to look into Hyperapp for basically the exact reasons you mentioned.

You mentioned Elm a lot in this post, and for obvious reasons. Right now, Elm occupies my "favorite frontend framework" spot (which may have a lot to do with my love of Elm's typing). What about Hyperapp do you find easier to work with than Elm? Just syntax familiarity, or is there some other clutch workflow feature missing from Elm?

I think the syntax for sure -- Elm is a big jump because you need to learn the syntax, architecture, and functional programming. The barrier to entry is lower here. Also, since its just JavaScript, it's easier to work with libraries natively than in Elm. I also kind of disliked working with the data structures (i.e. linked lists are more fully featured than arrays) and Maybe's in Elm -- maybe that's just me though. I think if you added TypeScript or Flow into Hyperapp, you would get a pretty similar experience to Elm!

I started using HyperApp around a year ago, when its API was still heavily changing. I even created a small project with it and it was fun! There once were 'events' that you could use for a subscription mechanism. Now I think you can use the state-bound actions returned by the app function. See github.com/hyperapp/hyperapp/blob/...

I wonder what exactly you had in mind by "it's not as production ready as the aforementioned frameworks"? What did you feel is missing?

As far as I can tell it's excellent quality, has 100% code coverage and as it's small I could probably maintain it as if I had written it myself, though there is a community to help me. I saw the docs just got a major refresh which helps a lot.

Perhaps you meant the wider ecosystem of support and tooling is small? I discovered it is possible to use it with Create React App, a bastion of production readiness :). Also Visual studio and Browser F12 tools are excellent for debugging. Being small also I can pretty easily integrate almost any package I might want to without fighting with it.

As interesting as this is, for a small application like the one you describe in this post, I don't understand the seemingly obsessive necessity to use a framework like this.
I would like to understand why you prefer this over less than half the amount of vanilla code needed to produce identical functionality. Couldn't find a post by you yet talking about this.
Would you be so kind to provide insight?

for an application like this, probably not much of an advantage. But once you start adding complexity, muyltiple views, etc., the benefits of predictable state management, automatic rerendering on state change, and component-based architecture become extremely valuable. I don't think the point of this page is to be a tutorial on the best way to build a quote-fetching app, it is meant to be an introduction to hyperapp using a quote-fetching app as a simple, easy-to-understand entry point

I have been following the series of learning new things, and I learned some things along the way, so thanks for sharing. Now that you are in the functional programming, do you have thought about try elixir lang? I would like to read your opinions about it. I am currently moving with javascript, but I espect to use elixir in the future. (I'm learning English too ¯_(ツ)_/¯ )

I haven't done a ton of experience with functional languages! I have more experience implementing functional paradigms in non-functional languages. I looked into Elixir a bit -- Phoenix looks a ton like Rails to me which is fascinating! Maybe I'll try!