WebReflection / uce-template

A Vue 3 inspired Custom Elements toolless alternative.
https://medium.com/@WebReflection/a-new-web-components-wonder-f9e042785a91
ISC License
108 stars 7 forks source link

CustomElementRegistry error #4

Closed ArthurClemens closed 3 years ago

ArthurClemens commented 3 years ago

I am trying out a new project with NextJS with uce-template, and I am getting a dreaded error:

Uncaught DOMException: Failed to execute 'define' on 'CustomElementRegistry':
the name "uce-template" has already been used with this registry

The code is not spectacular:

// lib/useUceLoader.js

import loader from "uce-loader";
import { useEffect } from "react";

export const useUceLoader = () => {
  useEffect(() => {
    loader({
      on(component) {
        // first component found, load uce-template
        if (!this.q) {
          this.q = [component];
          const script = document.createElement("script");
          script.src = "https://unpkg.com/uce-template";
          document.body.appendChild(script).onload = () => {
            // get the uce-template class to use its .from(...)
            this.Template = customElements.get("uce-template");
            // load all queued components
            for (var q = this.q.splice(0), i = 0; i < q.length; i++)
              this.on(q[i]);
          };
        }
        // when uce-template is loaded
        else if (this.Template) {
          // ignore loading uce-template itself
          if (component !== "uce-template") {
            // load the component on demand
            fetch(`/webcomponents/${component}.uce`)
              .then((body) => body.text())
              .then((definition) => {
                document.body.appendChild(this.Template.from(definition));
              });
          }
        }
        // if uce-template is not loaded yet
        // add the component to the queue
        else this.q.push(component);
      },
    });
  }, []);
};
import { useUceLoader } from '../lib/useUceLoader';

export default function Home() {
  useUceLoader();
  return (
    <my-btn />
  );
};
WebReflection commented 3 years ago

which version of the loader are you using? it is also possible you push twice the same component ... the last else should likely be instead:

else if (this.q.indexOf(component) < 0)
  this.q.push(component);
WebReflection commented 3 years ago

actually ... it is very possible you are trying to inject uce-template itself, or you import uce-template somewhere in your code

ArthurClemens commented 3 years ago

Not sure what I am doing wrong.

WebReflection commented 3 years ago

that is not a reproducible example to me ... there's no layout, no live-demo, so if you could provide that, it'd be awesome.

ArthurClemens commented 3 years ago

I have created a test repo: https://github.com/ArthurClemens/nextjs-uce-template

WebReflection commented 3 years ago

@ArthurClemens two issues:

  1. you are defining a builtin extend in .uce file, but you expose a generic htmlelement extend on the page
  2. components need the <template is="uce-template"> only if rendered on the page, files don't need that

To solve point 1 (index.js):

export default function Home() {
  useUceLoader();
  return (
    <>
      Page
      <button is="my-btn" />
    </>
  );

to solve point 2 (my-btn.uce):

<button is="my-btn">Clicked {{ times }} times!</button>
<script type="module">
  const states = new WeakMap();
  export default {
    setup(element) {
      const state = { times: 0 };
      states.set(element, state);
      return state;
    },
    onClick() {
      states.get(this).times++;
      // update the current view if the
      // state is not reactive
      this.render();
    },
  };
</script>

also note you can just name uce-btn.html and change the loader accordingly, if your editor doesn't handle .uce extensions 👋

ArthurClemens commented 3 years ago

Clear. Thanks for the help!

WebReflection commented 3 years ago

Thank you, I've just realized there is a bug with events set directly on the component ...

WebReflection commented 3 years ago

Amending: there was no bug, but the lib just got updated with better useEffect lifecycle.