Composi Without JSX

Although we love JSX because of its brevity and clarity, some people really dislike it.

You can use Composi without JSX. You have two options: the Composi h function or Hyperx-es6.

H

The h function lets you use hyperscript syntax to designate the HTML you want to create. When working with Composi, you will always be importing the h function into your files to enable Composi's virtual dom. A Composi project is automatically configured to let Babel know know to use it when dealing with JSX. So, whether you use JSX or h, both will result in the creation of the same virtual node. Take the following for example:

See the Pen Composi Tuts - Hyperx-1 by Robert Biggs (@rbiggs) on CodePen.

Now we can create the same result using h:

See the Pen Composi Tuts - Hyperx-2 by Robert Biggs (@rbiggs) on CodePen.

Both of these produce the same virtual node. As you can see, the h code looks quite similar to the virtual node that it creates:

// The virtual node created is:
{
  type: "h2", 
  props: {
    class: "title", 
    title: "Hello, Ellen!"
  }, 
  children: ["Hello, ", "Ellen", "!"]
}

Subcomponents With H

You can also create subcomponents when using h. You write a function that returns the required hyperscript. Then you enclude it as an interpolation in the parent. Because this is hyperscript syntax, you'll need to use ${} for interpolation:

See the Pen Composi Tuts - Hyperx-3 by Robert Biggs (@rbiggs) on CodePen.

If you prefer functional over classes, you will probably likeusing the h funtion.

taggers

Typing out tags with the h function can get verbose. We have created a hyperscript compatible NPM module called h-html. What this does is provide a more compact function named after each tag you want to create. You therefore only need to provide props and children.

Installing:

npm i -D taggers

Example usage:

import {h, mount} from 'composi'
import {taggers} from 'taggers'

const {nav, h1} = taggers(h)

// Define tags:
function title(message) {
  return nav(
    {}, 
    h1(
      {}, 
      'Hello, ${message}!'
    )
  )
}
// Mount the component:
mount(title('World'), 'header')

And here's a Codepen example:

See the Pen Composi with taggers-1 by Robert Biggs (@rbiggs) on CodePen.

h-html

Like Taggers, there is also h-html, a module that allows you to use tag shortcuts. It's nearly double the size of taggers, but easier to use. No need to pass in the h, function, etc.

Installing:

npm i -D h-html

After installing, you can import it into your project. There are two ways you can do so, importing indidual tags, or importing them all on a alias.


import {h, mount} from 'composi'
import {nav, h1} from 'h-html'

// Define tags:
function title(message) {
  return nav(
    {}, 
    h1(
      {}, 
      'Hello, ${message}!'
    )
  )
}
// Mount the tags:
mount(title('World'), 'header')

And here's a Codepen example:

See the Pen Composi with h-html-1 by Robert Biggs (@rbiggs) on CodePen.

Here's an example importing all tags as an alias:

import {h, mount} from 'composi'
import * as t from 'h-html'

// Define tags:
function title(message) {
  return t.nav(
    {}, 
    t.h1(
      {}, 
      'Hello, ${message}!'
    )
  )
}
// Mount the title:
mount(title('World'), 'header')

// Define list:
function list(data) {
  // Define list Item:
  function listItems(data) {
    return data.map(item => t.li({}, `Item ${item}`))
  }
  return t.ul(
    {class: 'list'},
    listItems(data)
  )
}
// Mount the list:
mount(list(['One', 'Two', 'Three']), 'section')

It's totally up to you which way you want to import h-html. However, if you know you are going to use a lot of tags, it makes sense to import them on an alias.

And here's a Codepen example of tags being aliased:

See the Pen Composi with h-html-2 by Robert Biggs (@rbiggs) on CodePen.

Hyperx-es6

Another alternative to JSX is Hyperx. The original version is in CommonJS format and cannot be easily imported into a Composi project. Therefore we've create a clone called Hyperx-es6. The only difference is that Hyperx-es6 gets exported as an ES6 module. This means you can use normal ES6 module import syntax and Rollup and bundle it properly. Hyperx-es6 allows you to ES6 template literal instead of JSX. The results are the same. The biggest difference in use will be in the text editor. JSX with get proper syntax highlighting, whereas Hyperx-es6 template literals will be treated as strings.

Hyperx-es6 Converts Template Literals into Hyperscript

Hyperx-es6 converts template literals into the same format as JSX and h. In this case, since we tell Hyperx-es6 to use the Composi h function, the result will be a virtual node that Composi can use.

Installation and Use

You'll need to install Hyperx-es6 in your project and import it into any file where you want to use it. You'll have to make an update to your project's gulpfile.js to know to include Hyperx-es6 when it bundles all the dependencies. And you'll also need to let Babel know to use Hyperx-es6 instead of Composi's h function for creating virtual nodes.

# cd to your project and run:
npm i -D hyperx-es6

In your project's app.js file add:

import {h, Component} from 'composi'
import {hyperx} from 'hyperx-es6'

// Tell Hyperx-es6 to use the Composi h function,
// by passing it to Hyperx-es6:
const html = hyperx(h)]

With this in your file, you can start using Hyperx-es6. You could make functional components like with JSX, or use it inside of a class component. Below are some functional components with composition. We need to use ${} for interpolation. Note that when using Hyperx, you'll be using the tagged template literal html that you designated after importing Hyperx-es6. Note: in all the following Codepen examples, we're using the UMD version of Hyperx-es6 that we can load in the browser and access as a global variable.

See the Pen Composi Tuts - Hyperx-3 by Robert Biggs (@rbiggs) on CodePen.

Using Hyperx-es6 with a Class Component

You can also use Hyperx-es6 with class-based components. In the example below we have subcomponents using Hyperx-es6, listItem and disclosure. We integrate them into the parent component List, which is an extension of Component. Because the subcomponents are functions, we need to invoke them with interpolation, so they get enclosed with ${}. Our List component also implements events. You can click on a list item to get an alert and you can add a new list item as well.

See the Pen Composi Tuts - Hyperx-4 by Robert Biggs (@rbiggs) on CodePen.

Load From a CDN

You can also load Hyperx-es6 from a CDN:

<script src='https://unpkg.com/composi@0.9.1/dist/composi.js'></script>
<script src='https://unpkg.com/hyperx-es6@2.3.2/dist/hyperx-es6.js'></script>

When you load Hyperx-es6 from a CDN, you can access it like this:

const { h, render, Component } = composi
// When using CDN version, notice capitalized: Hyperx.
// ES6 import is lowercase: import {hyper} from 'hyper-es6'
const {hyperx} = Hyperx

// Tell Hyperx-es6 to use the Composi h function,
// by passing it to hyperx:
const html = hyperx(h)
// Start using html`` to define component markup.