You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The [React documentation around using React in Web Components](https://reactjs.org/docs/web-components.html#using-react-in-your-web-components) presents a case where you can create Web Components using React, but when explored, utilizing React in Web Components presents some significant functionality issues, as detailed in [this issue](https://github.com/facebook/react/issues/9242). Namely, complex React apps rendered in Web Components lose their functionality.
8
+
This package works with React at version 17. For version 16, [see the react-16
9
+
branch of this repo](tree/react-16).
9
10
10
-
## The Solution
11
+
## What is it?
11
12
12
-
`react-html-element`seamlessly creates the glue needed to utilize React in your Web Components without losing functionality.
13
+
`react-html-element`gives a few quality of life improvements over simply
13
14
14
15
## Installation
15
16
@@ -50,28 +51,22 @@ import ReactHTMLElement from 'react-html-element';
The key pieces of code are `... extends ReactHTMLElement` and `this.mountPoint`.
61
+
The key pieces of code are `... extends ReactHTMLElement` and `this.render`,
62
+
which mounts our app to its designated `mountPoint`, [as described below](#thismountpoint-and-using-custom-templates).
61
63
62
64
> ### Polyfills
63
65
>
64
-
> One thing to remember is that you will need to load [the webcomponentsjs polyfills](https://www.webcomponents.org/polyfills) for `ReactHTMLElement` to work in all browsers. Be sure to include [the ES5 adapter](https://github.com/webcomponents/polyfills/tree/master/packages/webcomponentsjs#custom-elements-es5-adapterjs), as we currently transpile `ReactHTMLElement` down to ES5. The polyfills should be in the `<head>`, and should look something like this:
66
+
> One thing to remember is that you will need to load [the webcomponentsjs polyfills](https://www.webcomponents.org/polyfills) for `ReactHTMLElement` to work in all browsers.
> <!--- We use the closing bracket of this comment to close off the above opening comment, if it gets written -->
75
70
> ```
76
71
>
77
72
> There are many ways to implement these polyfills, and you can explore them in the [webpcomponentsjs README](https://github.com/webcomponents/polyfills/tree/master/packages/webcomponentsjs#how-to-use).
@@ -113,7 +108,7 @@ import ReactHTMLElement from 'react-html-element';
@@ -136,11 +131,10 @@ Using styled-components with ReactHTMLElement seems tricky, but there's actually
136
131
```jsx
137
132
classReactWebComponentextendsReactHTMLElement {
138
133
connectedCallback() {
139
-
ReactDOM.render(
134
+
this.render(
140
135
<StyleSheetManager target={this.shadow}>
141
136
<App />
142
-
</StyleSheetManager>,
143
-
this.mountPoint
137
+
</StyleSheetManager>
144
138
);
145
139
}
146
140
}
@@ -149,7 +143,8 @@ class ReactWebComponent extends ReactHTMLElement {
149
143
`this.shadow` is a getter that will initialize your Web Component, attaching a Shadow
150
144
Root with `{mode: 'open'}`, and setting the Shadow Root's innerHTML to your
151
145
template or `<div></div>`. If this initialization has already occurred, it will
152
-
simply return the previously created Shadow Root.
146
+
simply return the previously created Shadow Root. `this.mountPoint` utilizes
147
+
`this.shadow` as part of its work to generate the Shadow Root.
153
148
154
149
We use `this.shadow` for the styles instead of simply using `this.mountPoint` because of unmounting. If stylesheets are a child of `this.mountPoint`, ReactDOM will throw an error when you try to unmount. (`unmountComponentAtNode(): The node you're attempting to unmount was rendered by another copy of React.`) This error is a little cryptic, but the bottom line is that ReactDOM expects that everything inside the mounted node was generated by React itself. When we use the same node to place our styles, it breaks that expectation. Using the `this.shadow` will cause the styles to be placed as a first-child of the Shadow DOM, but not inside the same component where our app is mounted.
0 commit comments