The problem is creating sophisticated web applications and dealing with the complexity of the tools we have at our disposal.
HyperApp was born out of the attempt to do more with less. We have aggressively minimized the concepts you need to understand while remaining on par with what other frameworks can do. What makes HyperApp unique among the alternatives like React, Preact, and Mithril, is its compact API, built-in state management, and the unrivaled, small bundle size.
In this article, I'll introduce you to HyperApp and walk you through a few code examples to help you get started. Experience with other frameworks is not required, but since you are interested in HyperApp, I'll assume you have some knowledge of HTML and JavaScript.
What is HyperApp?
HyperApp helps you build interactive web applications. It follows many of the principles popularized by React like one-way data flow, JSX, and Virtual DOM.
HyperApp is based on the Elm Architecture. This means that application design is like application design in Elm or React/Redux.
import { h, app } from "hyperapp"
app({
state: "Hi.",
view: state => <h1>{state}</h1>
})
The examples in this article use JSX for familiarity, but you are not required to use JSX with HyperApp.
Here is the example above using Hyperx and ES6 template literals.
import { h, app } from "hyperapp"
import hyperx from "hyperx"
const html = hyperx(h)
app({
state: "Hi.",
view: state => html`<h1>${state}</h1>`
})
And for completeness, here is the example again without using external libraries.
import { h, app } from "hyperapp"
app({
state: "Hi.",
view: state => h("h1", null, state)
})
Concepts
Virtual Nodes
HyperApp exposes h
, a function that follows the HyperScript signature and is used to create virtual nodes.
h("div", { id: "app" }, [
h("h1", null, "Hi.")
])
A virtual node is a JavaScript object that describes an HTML/DOM tree. The example above produces the following object:
{
tag: "div",
data: {
id: "app"
},
children: [{
tag: "h1",
data: null,
children: ["Hi."]
}]
}
JSX is a JavaScript language extension used to represent dynamic HTML. Hyperx is an ES6, standards compliant alternative. Both boil down to the same h
function call behind the scenes.
Hyperx/JSX in:
<main id="app">Hi.</main>
Vanilla out:
h("main", { id: "app" }, "Hi.")
The state, view, and actions
'Hello World' gets boring fast. Here is an interactive example using the essential ingredients of every HyperApp application.
app({
state: 0,
view: (state, actions) => (
<main>
<h1>{state}</h1>
<button onclick={actions.add}>+</button>
<button onclick={actions.sub}>-</button>
</main>
),
actions: {
add: state => state + 1,
sub: state => state - 1
}
})
The state represents the entire data model of your application. In this case, it is a number and its initial value is 0.
state: 0
When the app
function runs, the state is passed to the view and its value is displayed inside an <h1>
tag.
<h1>{state}</h1>
There are also two buttons in the view that have onclick
handlers attached to them. The handlers are the actions that get passed to the view as the second argument.
<button onclick={actions.add}>+</button>
<button onclick={actions.sub}>-</button>
Notice that neither actions.add
or actions.sub
update the state directly, instead, they return a new state.
add: state => state + 1,
sub: state => state - 1
When the state is updated as a result of calling an action, the view function is called and the application is rendered again.
Visualizing the architecture
Users call actions by interacting with the application and they are the only available mechanism to update the state. Under the hood, HyperApp injects actions with code that knows when to render the application.
Actions that have no side effects are also known as reducers. If you are coming from Redux, this will make sense right away. A reducer is a pure function that receives the current state of the application and some data to compute a new state.
Visualize a chain in which each link represents a state configuration. The most recent link in the chain is the current state. The view function receives the current state and actions and uses them to construct the DOM tree. When an action is called, a new link in the chain is created.
Side effects
You can call multiple actions inside an action. You can call actions inside a callback passed to an asynchronous function like fetch too.
HyperApp knows that if an action returns null
or undefined
the state does not need to change and it skips the render pipeline. Incidentally, if an action returns a Promise, HyperApp does not update the state either and leaves it up to the resolve callback to figure out what to do, e.g., call other actions.
Examples
GIF search box
Let's build a GIF search box using the Giphy API. In this example, we'll demonstrate how to update the state asynchronously.
Continue reading %HyperApp: The 1 KB JavaScript Library for Building Front-End Apps%
by Jorge Bucaran via SitePoint