[005.3] Introduction to Choo

How and Why Choo can be a good choice for your next app

Subscribe now

Introduction to Choo [12.21.2017]

Yesterday we introduced Bankai. It’s a friendly web compiler with some interesting tools included. We also mentioned Choo, a JavaScript framework.

A quick overview

We will start our project from the tag in the last episode. In that episode, we copied the counter made in Choo to our project, just to get something working. Now, it's time take a look at the counter, and try to understand it.

vim index.js

So, here is the code from the counter. We will walk through each piece.

var html = require("choo/html");
var devtools = require("choo-devtools");
var choo = require("choo");

var app = choo();
app.use(devtools());
app.use(countStore);
app.route("/", mainView);
app.mount("body");

function mainView(state, emit) {
  return html`
    <body>
      <h1>count is ${state.count}</h1>
      <button onclick=${onclick}>Increment</button>
    </body>
  `;

  function onclick() {
    emit("increment", 1);
  }
}

function countStore(state, emitter) {
  state.count = 0;
  emitter.on("increment", function(count) {
    state.count += count;
    emitter.emit("render");
  });
}

Starting by the imports, we can see the requires. Then we can figure out that Choo does not use ES6 modules. For the moment, they do not support it.

var html = require("choo/html");
var devtools = require("choo-devtools");
var choo = require("choo");

To overcome this, they use browserify, which makes the browser accept the 'requires'.

The next piece of code is the initialization of our app. It uses the Choo API. A simple API with just a few methods. The method use makes the Choo instance read messages from stores or any events

Here we are using choo-devtools, and we can also add the stores we want.

var app = choo();
app.use(devtools());
app.use(countStore);
app.route("/", mainView);
app.mount("body");

In this case, we have countStore. This is just a callback function, which receives the state and an emitter. Under the hood, it uses nanobus.

function countStore(state, emitter) {
  state.count = 0;
  emitter.on("increment", function(count) {
    state.count += count;
    emitter.emit("render");
  });
}

Routing with Choo is simple. We are using the route method, passing the route name and the handler of this route. The handler is a function that receives the state and emit. We will use the state and emit when creating our views.

app.route("/", mainView);

We mount and start the app by using the mount method.

Our view is a function that receives the state and an emit function. This is how our view can emit/dispatch actions to our store, and receive the data updated from the store.

function mainView(state, emit) {
  return html`
    <body>
      <h1>count is ${state.count}</h1>
      <button onclick=${onclick}>Increment</button>
    </body>
  `;

  function onclick() {
    emit("increment", 1);
  }
}

Here for instance, we have an onClick function,and it emits the message increment and passing 1 as the payload. If you have used redux, this way is similar to dispatch actions.

The HTML is rendered by the help of bel, creating DOM elements from Template Strings.

We just saw a simple example on how to use Choo.

Create our choo app

Now, let’s try to bootstrap a Choo application with the Create choo app. It already contains some generators, which will help bootstrap our app.

We can use it directly if we are using an npm version greater than 5.2. Our app name will be first-choo-app.

npx create-choo-app first-choo-app

The generated code comes with a store, manifest, service worker and some other libraries already included. Let's run it.

Starting the server, and we can see the counter we just saw. Let's add a new page to our app. An About page.

To create our view, which will be called about, we can use Choo scaffold.

npx choo-scaffold view about

It creates a view/about file. We need to create a route for this view.

vim index.js

Our route will be /about. The function that will handle it will be our about file, which exports a function receiving the state and emit.

app.route("/", require("./views/main"));
app.route("/about", require("./views/about"));
app.route("/*", require("./views/404"));

To finish up, let’s see what the about view looks like, and show an h1 message on it.

var html = require("choo/html");

module.exports = view;

function view(state, emit) {
  return html`
    <body>
      <h1>This is our about page</h1>
    </body>
  `;
}

Now, go back to our running app and visit the /about page. It renders exactly what we expected. Sweet!

If you have never used Choo, try it now. I think you will fall in love.

Summary

Today we saw Choo. It's a sturdy front-end framework, which is very small, simple and beautiful. Furthermore, Choo has an interesting ecosystem around it.

Resources