React 19 and Web Component Examples
React 19 and Web Component Examples êŽë š
There is lots of news of React 19 and going stable and now supporting Web Components. Or⊠âcustom elementsâ I should say, as that refers to the HTML expression of them as <dashed-elements>
, which is where the trouble laid. Apparently it was hard for React to know, in JSX, if props should be treated as a property or an attribute. So theyâve just decided this is how it will work:
props passed to a custom element will render as attributes if their type is a primitive value like string
, number
, or the value is true
. Props with non-primitive types like object
, symbol
, function
, or value false
 will be omitted.
props that match a property on the Custom Element instance will be assigned as properties, otherwise they will be assigned as attributes.
Thatâs enough to pass all the tests at Custom Elements Everywhere, which tracks such things. (And apparently every single framework is now 100% fine. Cool.)
This got me thinking about what this actually means and how I might make use of it. I use both React and Web Components sometimes, but only rarely do I combine them, and the last time I did I had more issues with the Shadow DOM than I did with React doing anything funky.
So here Iâve made a LitElement and rendered it within a React component:
What I was thinking there was⊠what if I make a <designsystem-button>
and need a click handler on it? Turns out thatâs not really a problem. You can just slap a React onClick
right on it and itâs fine.
<MyCard>
<p>blah blah</p>
<!-- this is fine -->
<designsystem-button onClick={() => {}}></designsystem-button>
</MyCard>
That wasnât a problem anyway, apparently.
What is a problem is if I want to send in a function from React-land for the Web Component to call. Youâd think we could send the function in how LitElement generally wants you to do that like:
<!-- nope -->
<designsystem-button .mySpecialEvent=${specialEvent}>
But nope, JSX really doesnât like that âdot syntaxâ and wonât compile.
So you gotta send it in more like this:
<designsystem-button onSpecialEvent={() => mySpecialEvent()}
Then in order to âcallâ that event, you âdispatchâ and event named properly. Like:
this.dispatchEvent(new CustomEvent("SpecialEvent", { bubbles: true }));
Hereâs that with a ârawâ Web Component:
I took that idea from Jared Whiteâs article Oh Happy Day! React Finally Speaks Web Components. Where heâs got some other examples. Another is passing in a âcomplex objectâ which is one of those things that would have been impossible in React 18 and under apparently, and now we can do: