Tonic web components with signals for state sync

Published on 21 January 2023

I‘ve been looking into Tonic, a tiny web-components wrapper. Combining it with preact core signals to add state synchronisation is just a few lines: 
export class Component extends Tonic { 
  _set(...args) {
    effect(() => {
      super._set(...args)
    })
  }
}

Adding an optimised ${value} wrapper that only rerenders the changed value is another extension on the Component class:

...
html(strings, ...values) {
  const modifiedValues = values;
  values.forEach((value, index) => {
    if (value instanceof Signal) {
      modifiedValues[index] = super.html`<signal-wrapper signal=${value}></signal-wrapper>`;
    }
  })
  return super.html(strings, ...modifiedValues);
}
...
And then define the <signal-wrapper> component that gets injected in places where signal is passed without .value reads:

class SignalWrapper extends Tonic {
  // don’t render initially, FIXME: do I need it?
  preventRenderOnReconnect = true
  
  render() {
    return this.html`${this.props.signal.value}`;
  }

  connected() {
    this.unsubscribe = effect(() => {
      this.props.signal.value;
      this.reRender();
    })
  }

  disconnected() {
    this.unsubscribe();
  }
}