React & htmx

<script 
    src="https://unpkg.com/react@18/umd/react.development.js" 
    integrity="sha384-0HL/VWVbwweJfp0saUL50fXRuSABCdVeinTBoJCDXprLkJ49VI0QMWNGMRt8ebnT" 
    crossorigin="anonymous"></script>
<script 
    src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" 
    integrity="sha384-79Od0yhavbvtuP2nWl+Y6mwgs8AlknSIikYSw0+uOc65GTyH8SW7e2hCyCB303Y2" 
    crossorigin="anonymous"></script>
<script 
    src="https://unpkg.com/htmx.org@1.8.2" 
    integrity="sha384-+8ISc/waZcRdXCLxVgbsLzay31nCdyZXQxnsUy++HJzJliTzxKWr0m1cIEMyUzQu" 
    crossorigin="anonymous"></script>
customElements.define(
    "react-root",
    class extends HTMLElement {
        constructor() {
            super();
            this.attachShadow({mode: "open"});
            this.root = null;

            new MutationObserver(() => this.render()).observe(
                this,  {
                    subtree: true,
                    childList: true, 
                    attributes: true, 
                    attributeFilter: ["props", "type"],
                });
        }

        render() {
            if(this.root == null) {
                this.root = ReactDOM.createRoot(this.shadowRoot);
            }
                                    
            const element = window[this.rootType];
            if(element == null) {
                throw new Error(`Could not find component ${this.rootType}`);
            }

            this.root.render(
                React.createElement(
                    element, 
                    {root: this, ...this.rootProps},
                ),
            );
        }

        get rootType() {
            const el = this.querySelector("react-element");
            return (el != null) ? el.getAttribute("type") : null;
        }

        get rootProps() {
            const el = this.querySelector("react-element");
            return (el != null) ? JSON.parse(el.getAttribute("props")) : null;
        }

        set rootType(value) {
            const el = this.querySelector("react-element");
            if(el == null) throw new Error("Not template element found");
            el.setAttribute("type", value);
        }

        set rootProps(value) {
            const el = this.querySelector("react-element");
            if(el == null) throw new Error("Not template element found");
            el.setAttribute("props", JSON.stringify(value));
        }

        disconnectedCallback() {
            if(this.root != null) {
                this.root.unmount();
                this.root = null;
            }
        }
    }
);