πŸ”—Slot as templates

Introduction

Slots are a powerful feature when working with webcomponents that use the shadowDOM. And thanks to the hook @atomico/hooks/use-slot you will be able to observe the state of the slot and know the childNodes of this to manage the logic of the template. For example:

import { useRef } from "atomico";
import { useSlot } from "@atomico/hooks/use-slot";

function component() {
  const refSlotIcon = useRef();
  const slotIcon = useSlot(refSlotIcon);
  return (
    <host shadowDom>
      <slot
        name="icon"
        ref={refSlotIcon}
        style={slotIcon.length ? null : "display: none"}
      />
      <slot />
    </host>
  );
}

Thus managing to easily condition parts of our template to define the slots.

Another trick that useSlot allows us is the interaction at the DOM level, example:

import { useRef, useEffect } from "atomico";
import { useSlot } from "@atomico/hooks/use-slot";

function component() {
  const refSlotSlides = useRef();
  const slotSlides = useSlot(refSlotSlides);

  slotSlides.forEach((slide) => {
    slide.style.width = "100%";
    slide.style.height = "300px";
  });

  return (
    <host shadowDom>
      <slot name="slides" />
    </host>
  );
}

We can even apply filters per instance for a better identification of the node, example:

useSlot(refSlotSlides).filter(
  (childNode) => childNode instanceof HTMLDivElement
);

⚠️ In case of high ui computation use prefer to use slot modifiers inside a useEffect.

Slot pattern as a template

Slots are not only limited to a static definition, you can use them to identify a node and use it to create new nodes according to the logic of the webcomponent, example:

import { useRef, usePromise } from "atomico";
import { useSlot } from "@atomico/hooks/use-slot";

function userFetch() {
  const refSlotTemplateUser = useRef();
  const [Template] = useSlot(refSlotTemplateUser);
  const promise = usePromise(
    () =>
      fetch("https://jsonplaceholder.typicode.com/users").then((res) =>
        res.json()
      ),
    [],
    true
  );

  return (
    <host shadowDom>
      <slot name="template" ref={refSlotTemplateUser} />
      <div class="list">
        {promise.fulfilled
          ? !!Template &&
            promise.result.map((props) => <Template {...props} cloneNode />)
          : "Pending..."}
      </div>
    </host>
  );
}

Thanks to useSlot(refSlotTemplateUser) we get the first node of the Template slot to be used in the iteration of the results obtained by fetch, with this we have eliminated the leverage of the webcomponent in charge of rendering the user at the level of our webcomponent userFetch

Example

⚠️ the cloneNode property is available from version atomico@1.37.0

Last updated