cft
Become a CreatorSign inGet Started

Hyperscript - the hidden language of React

React uses JSX to make things easier for the developers. But every abstraction has its cost. Let's find out how JSX works under the hood and why it works like this!


user

Nikita Grechino

3 months ago | 3 min read
Follow

hyperscript-hidden-language-react-9j1qy

JSX is the starting point

React uses JSX to make things easier for the developers. So when you write something like this.

<div id="foo">

Hello!

</div>

Babel transforms it to plain JavaScript.

React.createElement("div", { id: "foo" }, "Hello!");

React.createElement is a function that creates a virtual node.It's a well-known fact, so what's the point?

Preact way

If you've used Preact before, you may notice it has an unobvious export in its source code.

export {

createElement,

createElement as h

} from β€œ./create-element”;

To make things clear, the createElement function from Preact serves the same needs as React.createElement. So the question is, why is it exported as h as well?

The reason is dead simple. It's exported as h because it's a hypescript function.So what exactly is hypescript?

Hyperscript is the key

Hypescript is a kind of language to create HyperText with JavaScript and was started by Dominic Tarr in 2012. He was inspired by markaby, the "short bit of code" to write HTML in pure Ruby.Markaby allows doing things like that.

require 'markaby'

mab = Markaby::Builder.newmab.html do

head { title "Boats.com" }

body do

h1 "Boats.com has great deals"

ul do

li "$49 for a canoe"

li "$39 for a raft"

li "$29 for a huge boot that floats and can fit 5 people"

end

end

end

puts mab.to_s

And the h function allows doing essentially the same thing, but with different syntax.

h = require("hyperscript");

h("div#foo", "Hello!");

It also supports nesting and CSS properties.

h = require("hyperscript");

h("div#foo",

h("h1", "Hello from H1!", { style: { 'color': 'coral' } })

);

Check out an interactive demo to see how it works.

Get your hands dirty

Now when we know what the h function does and why we need it, let's write our own version of it. Complete example can be found on codesanbox.

First, let's make up a render function, that creates real DOM elements from our virtual nodes.

const render = ({ type, children, props }) => {

const element = document.createElement(type);

if (props) {

for (const prop in props) {

element.setAttribute(prop, props[prop]);

}

}

if (children) {

if (Array.isArray(children)) {

children.forEach(child => {

if (typeof child === 'string') {

element.innerText = child;

} else {

element.appendChild(render(child));

}

})

} else if (typeof children === 'string') {

element.innerText = children;

} else {

element.appendChild(render(children));

}

}

return element;

}

Than, let's create the h function.

const h = (type, children, props) => {

let handledType = typeof type === 'string' ? type : 'div';

return {

type: handledType,

props,

children

}

}

Finally, let's create an actual content with our h function, render it with our render function and mount the result to the DOM.

const div = render(

h('div',

[

h('h1', 'Hello!', { id: 'foo' }),

h('h2', 'World!', { class: 'bar' })

],

));

document.querySelector('#app').appendChild(div);


P.S. Follow me on Twitter for more content like this!

Upvote


user
Created by

Nikita Grechino

Follow

Frontend developer

πŸ‘¨β€πŸŽ“ Blog to afford CS degree βš›οΈ Help people learn JavaScript & React in-depth πŸ’» Front-end dev πŸ”₯ FI/RE πŸ“₯ DM in Twitter for questions


people
Post

Upvote

Downvote

Comment

Bookmark

Share


Related Articles