DEV Community

artydev
artydev

Posted on

'htm is JSX-like syntax in plain JavaScript', but...

HTM stands for 'Hyperscript Tagged Markup', written by Jason Miller,
who is also the creator of the awesome library Preact.

Here is how to use it :

import { render } from 'preact';
import { html } from 'htm/preact';
render(html`<a href="/">Hello!</a>`, document.body);
Enter fullscreen mode Exit fullscreen mode

What's nice, it's that you can use it with any frameworks.
For example in Mithril :

 const html = htm.bind(m);

 const Ciao = function ({attrs}) {
   return {view: () =>  html`<h1>Hello ${attrs.name}</h1>`}
 }
 m.render(app, m(Ciao, {name: "Raph"}))
Enter fullscreen mode Exit fullscreen mode

In React :

import ReactDOM from 'react-dom';
import { html } from 'htm/react';
ReactDOM.render(html`<a href="/">Hello!</a>`, document.body);
Enter fullscreen mode Exit fullscreen mode

As you can see, in order display the component, you have to pass it to a 'render' function, specific to the framework used.

Wouldn't it be nice if we could do ? :

let HelloWorld = html`<h1>Hello</h1>`
document.body.append(HelloWorld)
Enter fullscreen mode Exit fullscreen mode

It turns out it's indeed possible HTML to Dom Element :

import { html } from "sinuous"

let HelloWorld = html`<h1>Hello</h1>`
HelloWorld.style.color = "red";
document.body.append(HelloWorld)
Enter fullscreen mode Exit fullscreen mode

Here the 'html' function returns a real DOM element.
Thanks to Sinuous

There are really many advantages in doing so.
It is not unlike the nice library DML;

Here is another example IonicSinuous:

const { html, observable, map } = sinuous;

const Users = observable([]);

function Services() {
  async function fetchRandomUsers() {
    const response = 
        await fetch('https://randomuser.me/api/?results=10');
    const data = await response.json();
    Users(data.results);
  }
  return {
    fetchRandomUsers,
  };
}

const User = (user, index) => {
  let userView =  html`
      <ion-item style="display:none;">
        <ion-avatar style="margin-right:10px">
          <ion-img src=${user.picture.thumbnail}></ion-img>
        </ion-avatar>
        <ion-label>
          ${user.name.first} ${user.name.last}
        </ion-label>
      </ion-item>
    `;
  setTimeout(() => userView.style.display = "block" , 10 * index + 10)
  return  userView;
};


const App = () => {
  const svc = Services();
  return html`
    <ion-content style="text-align:center">
      <ion-button
        onclick=${svc.fetchRandomUsers}
      >
        Fetch Users
      </ion-button>
      <ion-list>
        ${() => Users().map((user,index) => User(user, index))}
      </ion-list>
    </ion-content>
  `;
};

document.body.appendChild(App());

Enter fullscreen mode Exit fullscreen mode

Discussion (0)