<h2>Understanding JSX</h2>

<p>
  This is an HTML page with a single babel-transpiled JS file and no dependencies.
  It is rendering DOM via JSX without any frameworks.
</p>
body {
  padding: 20px 20px 320px;
}
* {
  box-sizing: border-box;
}
pre {
  position: absolute;
  bottom: 0;
  left: 0;
  width: 100%;
  max-height: 300px;
  padding: 10px;
  margin: 0;
  background: #F3F3F3;
  border-top: 1px solid #CCC;
  box-shadow: inset 0 1px 10px rgba(0,0,0,0.2);
  font: 11px/1.1 Menlo,Monaco,'Courier New',courier;
  color: #555;
  overflow: auto;
}
View Compiled
/** @jsx h */

// ^^^^ this tells a transpiler to inject calls to an `h()` function for each node.

const ITEMS = 'hello there people'.split(' ');

// a "partial" that does a filtered loop - no template BS, just functional programming:
function foo(items) {
  // imagine templates that adhere to your JS styleguide...
  return items.map( p => <li> {p} </li> );    // <-- can be multiline
}

// a simple JSX "view" with a call out ("partial") to generate a list from an Array:
let vdom = (
  <div id="foo">
    <p>Look, a simple JSX DOM renderer!</p>
    <ul>{ foo(ITEMS) }</ul>
  </div>
);

// render() converts our "virtual DOM" (see below) to a real DOM tree:
let dom = render(vdom);

// append the new nodes somewhere:
document.body.appendChild(dom);

// Remember that "virtual DOM"? It's just JSON - each "VNode" is an object with 3 properties.
let json = JSON.stringify(vdom, null, '  ');

// The whole process (JSX -> VDOM -> DOM) in one step:
document.body.appendChild(
  render( <pre>{ json }</pre> )
);





/** Render Virtual DOM to the real DOM */
function render(vnode) {
  if (typeof vnode==='string') return document.createTextNode(vnode);
  let n = document.createElement(vnode.nodeName);
  Object.keys(vnode.attributes || {}).forEach( k => n.setAttribute(k, vnode.attributes[k]) );
  (vnode.children || []).forEach( c => n.appendChild(render(c)) );
  return n;
}

/** hyperscript generator, gets called by transpiled JSX */
function h(nodeName, attributes, ...args) {
  let children = args.length ? [].concat(...args) : null;
  return { nodeName, attributes, children };
}


/*
// here's an alternative hyperscript-to-vdom method that creates sparse nodes:
function h(nodeName, attributes, ...args) {
  let vnode = { nodeName };
  if (attributes) vnode.attributes = attributes;
  if (args.length) vnode.children = [].concat(...args);
  return vnode;
}
*/
View Compiled

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.