Postix II: Multipage app with routing, in Hyperapp

Rishav Sharan
4 min readJan 15, 2018

--

In the last story, we set up a development environment for our app and created a simple “Hello World” example. In this story, we will extend our last work and turn it into a multipage app with a functioning router and page components.
Here is the links to the entire series;

Postix I : Starting with “Hello World” in Hyperapp

Postix II: Mutipage app with routing, in Hyperapp ( < you are here)

Lets pick up from where we left off. Make sure you have the codebase from Part 1.

We will be using a Hyperapp module @hyperapp/router. Install the module with npm i --save @hyperapp/router

Now, let us define some simple pages in our src/pages folder.

Add in a Home.js file with the content;

import { h } from "hyperapp";
const Home = h("h1", {}, "Home")
export default Home

and a src/pages/About.js file with the content:

import { h } from "hyperapp";
const About = h("h1", {}, "About")
export default About

The Home page will show a simple H1 tag as <h1>Home</h1> and the About page will show <h1>About</h1> after the rendering is done.

Now we will create a Layout inside which our Home and About pages will be rendered. Add a new file src/components/Layout.js with the content:

import { h } from "hyperapp";

const Layout = (props, page) => h("div",{class:"container"}, [
h("article", {}, page),
])

export default Layout

Now, lets update our src/index.js to;

import { h, app } from "hyperapp";
import { Route, location } from "@hyperapp/router";

import Layout from "./components/Layout.js";
import Home from "./pages/Home.js";
import About from "./pages/About.js";

const state = {
location: location.state
};

const actions = {
location: location.actions
};

const view = () => h("div", {class:"main"}, [
h(Route, { path: "/", render: () => Layout({}, Home) }),
h(Route, { path: "/about", render: () => Layout({}, About) })
])

const main = logger()(app)(state, actions, view, document.body)
const unsubscribe = location.subscribe(main.location);

Before we go any further, lets just build the project and see what we have got working here. Run parcel in your terminal and fire up localhost:1234

The route should be working. If you type in localhost:1234 you will see the src/components/Layout.js being rendered with the tags from the src/pages/Home.js If you type in localhost:1234/about you will see the text “About” from the src/pages/About.js being rendered. We have a working router switching between 2 pages.

Lets look at the code again to better understand the flow. In src/index.js we have the block;

const view = () => h("div", {class:"main"}, [
h(Route, { path: "/", render: () => Layout({}, Home) }),
h(Route, { path: "/about", render: () => Layout({}, About) })
])

When the “/” route is called, Hyperapp renders the Layout({}, Home) function. Home here has been pulled in as an import `import Home from "./pages/Home.js";

Layout here at the end of the day, is just a function which takes in Home as an argument. In src/components/Layout.js we have the block;

const Layout = (props, page)  => h("div",{class:"container"}, [
h("article", {}, page),
])

In the case of the “/” route, Layout gets Home as the page argument and renders it.

Now, we will add in a Navbar at the top of the app to making navigating between the pages easy.

Add a new file src/components/Navbar.js with the content:

import { h } from "hyperapp";
import { Link } from "@hyperapp/router";

const Navbar = () => h("nav", {}, [
h(Link, {"to": "/" }, "Home"),
h(Link, {"to": "/about" }, "About")
])

export default Navbar

It will render a simple <nav> element with links to our two supported routes.

Link is a custom element provided by the router and enables us to route pages on the client side without refreshing the page.

Finally, lets update the Layout and add our new Navbar component in there.

import { h } from "hyperapp";

import Navbar from './Navbar.js'

const Layout = (props, page) => h("div",{class:"container"}, [
h(Navbar),
h("article", {}, page),
])

export default Layout

Hit save. run parcel and open localhost:1234

Congratulations. We now have a barebones webapp with multiple pages and working router in place. Its a good platform to build upon.

The code so far can be found here

--

--