Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
theengineear opened this issue Nov 15, 2024 · 0 comments

Comments

@theengineear
Copy link
Collaborator

Pros (for removal)

  • Removing it means less surface area / forks.
  • It’s potentially error-prone / hard to reason about (see context below).
  • It might force better architectural practices.

Cons (for removal)

  • It’s kinda hard to roll your own if you need this sort of thing.

Options

  • Just delete it from the interface — figure it out, bye (see rolling your own below)!
  • Add a way to register custom updaters (see #132).

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant