Netflix / x-element

A dead simple starting point for custom elements.
Apache License 2.0
29 stars 12 forks source link

Discussion: Should we remove “live” from the default template interface? #208

Open theengineear opened 2 days ago

theengineear commented 2 days ago

Pros (for removal)

Cons (for removal)

Options

Current usage

With live, you could do something like this:

static template(html, { live }) {
  return ({ value }) => {
    return html`<input id="input" .value="${live(value)}">`;
  };
}

Rolling your own

Without live, you would have to do something like this:

static template(html) {
  return ({ value }) => {
    return html`<input id="input">`;
  };
}

// After every render, make sure that current values are bound, even if they
//  haven’t changed from the perspective of the outer element.
render() {
  super.render();
  const input = this.shadowRoot.getElementById('input');
  if (input.value !== this.value) {
    input.value = this.value;
  }
}

Context

Under-the-hood, the live binding works by bypassing the value !== lastValue equality check. But, this only occurs on render. In other words, if the node-in-question changes and a re-render isn’t called… nothing happens. Even worse… since rendering is itself guarded by change-by-reference detection — there’s no guarantee that a top-level re-render would even make its way back to the live binding!

The reason a live binding is used is for the “controlled form” paradigm. The goal here is to have a single state store that fully declares the state of the form. But of course, there’s state in the DOM too (especially for form controls) — so we end up with competing sources of truth.

One alternative pattern is to let the form state live in the form (that kinda is how it’s designed in the first place) and avoid reentrance there altogether. But, that can be a tricky pattern as well.