Skip to content

Commit c12ca21

Browse files
committed
Docs: describing why this is useful with React 17
1 parent 27b4af8 commit c12ca21

File tree

1 file changed

+14
-19
lines changed

1 file changed

+14
-19
lines changed

README.md

Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@
33
[![Build Status](https://travis-ci.com/WTW-IM/react-html-element.svg?branch=master)](https://travis-ci.com/github/WTW-IM/react-html-element)
44
[![npm version](https://badge.fury.io/js/react-html-element.svg)](https://badge.fury.io/js/react-html-element)
55

6-
## The Problem
6+
## NOTE:
77

8-
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).
910

10-
## The Solution
11+
## What is it?
1112

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
1314

1415
## Installation
1516

@@ -50,28 +51,22 @@ import ReactHTMLElement from 'react-html-element';
5051

5152
class IncrementerComponent extends ReactHTMLElement {
5253
connectedCallback(): void {
53-
ReactDOM.render(<Incrementer />, this.mountPoint);
54+
this.render(<Incrementer />);
5455
}
5556
}
5657

5758
customElements.define('incrementer', ReactTestComponent);
5859
```
5960

60-
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).
6163

6264
> ### Polyfills
6365
>
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.
6567
>
6668
> ```html
6769
> <script src="https://cdnjs.cloudflare.com/ajax/libs/webcomponentsjs/2.4.3/webcomponents-bundle.js"></script>
68-
> <script>
69-
> if (!window.customElements) {
70-
> document.write('<!--');
71-
> }
72-
> </script>
73-
> <script src="https://cdnjs.cloudflare.com/ajax/libs/webcomponentsjs/2.4.3/custom-elements-es5-adapter.js"></script>
74-
> <!--- We use the closing bracket of this comment to close off the above opening comment, if it gets written -->
7570
> ```
7671
>
7772
> 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';
113108

114109
class IncrementerComponent extends ReactHTMLElement {
115110
connectedCallback(): void {
116-
ReactDOM.render(<Incrementer />, this.mountPoint);
111+
this.render(<Incrementer />);
117112
}
118113

119114
constructor(): void {
@@ -136,11 +131,10 @@ Using styled-components with ReactHTMLElement seems tricky, but there's actually
136131
```jsx
137132
class ReactWebComponent extends ReactHTMLElement {
138133
connectedCallback() {
139-
ReactDOM.render(
134+
this.render(
140135
<StyleSheetManager target={this.shadow}>
141136
<App />
142-
</StyleSheetManager>,
143-
this.mountPoint
137+
</StyleSheetManager>
144138
);
145139
}
146140
}
@@ -149,7 +143,8 @@ class ReactWebComponent extends ReactHTMLElement {
149143
`this.shadow` is a getter that will initialize your Web Component, attaching a Shadow
150144
Root with `{mode: 'open'}`, and setting the Shadow Root's innerHTML to your
151145
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.
153148

154149
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.
155150

0 commit comments

Comments
 (0)