Remix.run Logo
▲ mg 2 hours ago

What do you not like about WebComponents?

Say we want to make an icon that when clicked shows how often it was clicked. The webcomponent code seens quite sane to me:

   class HelloIcon extends HTMLElement {
      connectedCallback() {
        this.clickCount = 0;

        this.innerHTML = `
          <button class="icon">:)</button>
          <dialog>
            <p>Hello, I was clicked 0 times</p>
            <button class="close">Close</button>
          </dialog>
        `;

        const icon = this.querySelector('.icon');
        const dialog = this.querySelector('dialog');
        const closeBtn = this.querySelector('.close');
        const dialogText = this.querySelector('p');

        icon.addEventListener('click', () => {
          this.clickCount++;
          dialogText.textContent = `Hello, I was clicked ${this.clickCount} times`;
          dialog.showModal();
        });

        closeBtn.addEventListener('click', () => dialog.close());
      }
    }
Try it here:

https://plnkr.co/edit/0XUOLyM52xfFiIBu?open=index.html&previ...

▲Too an hour ago | parent | next [-]

I don't know if that's idiomatic webcomponent or not but that looks unmaintainable, even for such a minimal component, imagine once it grows. It's not separating presentation from state and logic. querySelector need to match classes and elements in the markdown. Mutating textContent is going to run out of sync as soon as you have more than one event source doing the same. Those are all problems that React solve by separating state and only rendering in one path.

▲kaoD an hour ago | parent | prev | next [-]

That's the best case scenario and already looks like crap. If that looks sane to you, I don't know what to say.

Make it have an initial count via attributes, sync it with the DOM so if the attribute changes the count resets, and make the JS property always match the attribute (and vice-versa) so it behaves sanely. You're in for a world of pain even for something as simple as this.

Plus they're not declarative: you will only make me use innerText-based updates by threatening me and my family.

Plus they only work with JS enabled, while I can use JSX in SSR.

I've worked extensively with Web Components. They suck.

▲pwdisswordfishq an hour ago | parent | prev | next [-]

For starters, that it introduces weird special cases to DOM parsing and structure, thereby breaking .isEqualNode whenever <template> elements are present.

▲jchw an hour ago | parent | prev | next [-]

Well for one thing, I don't find that to be particularly succinct or nice example. There's a lot going on there:

- HTML in a string. No syntax checks. If you interpolate it, you have to escape manually or you could create trivial XSS vulnerabilities. Your editor will probably not syntax highlight it, making it harder to tell when you break it.

- Manually formatted update logic that is redundant with the string. Not so bad here, but try formulating a practical large component.

- Completely ad-hoc state management, no reconciliation. Again, fine for Hello World, not fine after that.

Using raw WebComponents, your application has to care about all of this on its own and more. You can use templates and slots (which you should) but that makes this even messier IMO and brings back the split that React became famous for getting rid of. We left manual DOM reconciliation, ad-hoc data flow and non-reactive components that manually call a render routine at arbitrary points for a reason: it sucked. It made for buggier, harder to maintain code. It can be done, but usually any decent app will wind up encapsulating patterns into utilities that get reused. And... That's precisely why we want a good library. That's what I want, a library that packages up good reusable patterns for constructing UIs effectively.

And that's exactly my point, which is WebComponents or not, the solution is still basically the same, use libraries. Which begs the question: if I have to use Lit, what is the point of "using the platform"? What is WebComponents doing for me here that React wouldn't be? And in my case, I struggle to see it.

Interoperability? The old way of embedding external components works quite fine. Switching APIs where you pass a DOM node for something to mount into and get back an object with an API to one where you instantiate a component and communicate via properties and events feels like a strictly lateral move. I can't think of a condition where this would be particularly more convenient, but I can think of some where it is actually less. Next.

Isolation? Yes, WebComponents does add tools to provide better isolation between components. For some use cases this is a genuinely useful feature, although it also isn't without tradeoffs (I mean, the flexibility of having things be not isolated comes in clutch sometimes, it's hard to argue this.) But I use React primarily to construct components in an application, where I find this property more undesirable than desirable.

The one thing I thought could be cool with WebComponents is if you could build them in pure HTML when you only needed basic templating, but no: the design they went with always requires subclassing in JS AFAIK.

I could go on and get more specific, but I feel like people will pick everything I just said apart quite enough. I hope I'm at least able to make the case that:

- I do in fact, get the general gist of WebComponents.

- I still don't like it despite that.

▲TeMPOraL 8 minutes ago | parent [-]

> Isolation? Yes, WebComponents does add tools to provide better isolation between components. For some use cases this is a genuinely useful feature, although it also isn't without tradeoffs

I hate the guts of every site that uses those. Shadow DOM makes the site hard to operate and fix programmatically from user end.

I mean, these days I can just throw an LLM at it so I don't care as much, but sometimes I want to still do things hands-on. Not to mention, Shadow DOM is often a difference between "simple userstyle/userscript that is allowed at work by security extensions" vs "requiring things that are banned on corporate-managed browser".

▲JimDabell an hour ago | parent | prev | next [-]

Why are your component styles global not encapsulated within the component?

▲wetpaws an hour ago | parent | prev [-]

[dead]