Edit in JSFiddle

function reactive(obj, callback) {
  const wrapped = {}

  for (let key in obj) {
    let value = obj[key]

    Object.defineProperty(wrapped, key, {
      get: function reactiveGetter() {
        return value
      },
      set: function reactiveGetter(newValue) {
        console.log('setting value from', value, 'to', newValue)
        value = newValue
        callback()
      }
    })
  }

  return wrapped
}

const component = {
  el: document.getElementById('content'),
  data: { name: 'World' },
  render: function () {
    console.log('component renders', this.data)
    this.el.innerHTML = `<h1>Hello ${this.data.name}</h1>`
  }
}

component.data = reactive(component.data, component.render.bind(component))
component.data.name = 'Universe'
The classic:

<div id="content">…loading</div>