Categories
Preact

Preact — Using Web Components

Spread the love

Preact is a front end web framework that’s similar to React.

It’s smaller and less complex than React.

In this article, we’ll look at how to get started with front end development with Preact.

Web Components

We can render web components in our Preact component.

For example, we can write:

import { Component, render } from "preact";

window.customElements.define(
  "x-foo",
  class extends HTMLElement {
    constructor() {
      super();
      let tmpl = document.createElement("template");
      tmpl.innerHTML = `
        <b>I am in the shadown dom</b>
        <slot></slot>
      `;
      let shadowRoot = this.attachShadow({ mode: "open" });
      shadowRoot.appendChild(tmpl.content.cloneNode(true));
    }
  }
);

export default class App extends Component {
  render() {
    return <x-foo position={{ x: 10, y: 20 }}>foo bar</x-foo>;
  }
}
if (typeof window !== "undefined") {
  render(<App />, document.getElementById("root"));
}

We call customElements.define to create our web component.

Then we reference it in the App component and add our content inside the slot .

We can use the x and y properties by writing:

import { Component, render } from "preact";

window.customElements.define(
  "x-foo",
  class extends HTMLElement {
    constructor() {
      super();
      let tmpl = document.createElement("template");
      tmpl.innerHTML = `
        <b>I am in the shadown dom</b>
        <slot></slot>
      `;
      let shadowRoot = this.attachShadow({ mode: "open" });
      shadowRoot.appendChild(tmpl.content.cloneNode(true));
    }

    set position({ x, y }) {
      this.style.cssText = `left:${x}px; top:${y}px; position: absolute`;
    }
  }
);

export default class App extends Component {
  render() {
    return <x-foo position={{ x: 10, y: 20 }}>foo bar</x-foo>;
  }
}
if (typeof window !== "undefined") {
  render(<App />, document.getElementById("root"));
}

We add the position setter.

Then we set the this.style.cssText property to set the position of the x-foo component.

Therefore, the x-foo component has the position values applied to it.

We can also call methods in web component classes.

To do this, we assign a ref to the web component.

Then we can call the methods in the web component class:

import { render } from "preact";
import { useEffect, useRef } from "preact/hooks";

window.customElements.define(
  "x-foo",
  class extends HTMLElement {
    constructor() {
      super();
      let tmpl = document.createElement("template");
      tmpl.innerHTML = `
        <b>I am in the shadown dom</b>
        <slot></slot>
      `;
      let shadowRoot = this.attachShadow({ mode: "open" });
      shadowRoot.appendChild(tmpl.content.cloneNode(true));
    }

    set position({ x, y }) {
      this.style.cssText = `left:${x}px; top:${y}px; position: absolute`;
    }

    doSomething() {
      console.log("did something");
    }
  }
);

export default function App() {
  const myRef = useRef(null);

  useEffect(() => {
    if (myRef.current) {
      myRef.current.doSomething();
    }
  }, []);

  return <x-foo ref={myRef} />;
}
if (typeof window !== "undefined") {
  render(<App />, document.getElementById("root"));
}

We set the ref prop to the myRef ref object, which is created from the useRef hook.

Then in the useEffect callback, we call myRef.current.doSomething() method to call the doSomething method in the web component.

Listen to Web Component Events

We can listen to web components. For example, we can write:

import { render } from "preact";
import { useEffect, useRef } from "preact/hooks";

window.customElements.define(
  "x-foo",
  class extends HTMLElement {
    constructor() {
      super();
      let tmpl = document.createElement("template");
      tmpl.innerHTML = `
        <b>I am in the shadown dom</b>
        <slot></slot>
      `;
      let shadowRoot = this.attachShadow({ mode: "open" });
      shadowRoot.appendChild(tmpl.content.cloneNode(true));
    }

    set position({ x, y }) {
      this.style.cssText = `left:${x}px; top:${y}px; position: absolute`;
    }

    connectedCallback() {
      this.shadowRoot.addEventListener("click", function (e) {
        console.log("listend to click event");
        console.log(e);
      });
    }
  }
);

export default function App() {
  return <x-foo onclick={() => console.log("click")}>foo bar</x-foo>;
}
if (typeof window !== "undefined") {
  render(<App />, document.getElementById("root"));
}

We call addEventListener to add the click event listener to our web component.

And we set the onclick prop to assign an event listener for the click event.

So when we click on the text, we should see the console log from both event listeners called.

Conclusion

We can use web components directly in our Preact app.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *