DOM & Browserhard

Convert a virtual DOM object into real DOM

Given a JSON object representing a virtual DOM tree (`{ type, props, children }`), write a function that creates the corresponding actual DOM elements recursively.

Asked at Meta, Google

#DOM#recursion#virtual DOM

Answer

/*
  Input shape:
  {
    type: 'div',
    props: { class: 'container', id: 'app' },
    children: [
      { type: 'h1', props: {}, children: ['Hello World'] },
      { type: 'p',  props: { class: 'text' }, children: ['Paragraph'] }
    ]
  }
*/

function createElement(vnode) {
  // Text node
  if (typeof vnode === 'string' || typeof vnode === 'number') {
    return document.createTextNode(String(vnode))
  }

  const { type, props = {}, children = [] } = vnode
  const el = document.createElement(type)

  // Set attributes / props
  for (const [key, value] of Object.entries(props)) {
    if (key === 'className') el.setAttribute('class', value)
    else if (key.startsWith('on')) {
      el.addEventListener(key.slice(2).toLowerCase(), value)
    } else {
      el.setAttribute(key, value)
    }
  }

  // Recursively create children
  for (const child of children) {
    el.appendChild(createElement(child))
  }

  return el
}

// Usage (Mount)
document.body.appendChild(createElement({
  type: 'ul',
  props: { class: 'list' },
  children: [
    { type: 'li', props: {}, children: ['Item 1'] },
    { type: 'li', props: {}, children: ['Item 2'] },
  ]
}))

Source: javascript.plainenglish.io — Meta

Practise more DOM & Browser questions →