Skip to content
This repository was archived by the owner on Sep 7, 2022. It is now read-only.

Commit 3412b0b

Browse files
committed
docs: Rewrite docs to be up to date with latest.
1 parent 3227e19 commit 3412b0b

File tree

1 file changed

+48
-93
lines changed

1 file changed

+48
-93
lines changed

README.md

+48-93
Original file line numberDiff line numberDiff line change
@@ -1,128 +1,83 @@
11
# React Integration
22

3-
Use Custom Elements in your React components without resorting to hacks.
3+
Converts web components into React components so that you can use them as first class citizens in your React components.
44

5-
## Why
5+
- Web components become lexically scoped so you can use them as tag names in JSX.
6+
- Listen for custom events triggered from web components declaratively using the standard `on*` syntax.
7+
- Passes React `props` to web components as properties instead of attributes.
8+
- Works with any web component library that uses a standard native custom element constructor, not just Skate or native web components.
69

7-
For whatever reason you want to be able to use Custom Elements within your React components and be able to pass content to the Custom Elements. For example:
10+
## Usage
811

9-
```js
10-
const CustomElement = document.registerElement('custom-element', {
11-
prototype: Object.create(HTMLElement.prototype, {
12-
createdCallback () {
13-
// Just going to remove the elements but it's likely one would template
14-
// the elements and if it moves them, it would have the same effect.
15-
this.innerHTML = '';
16-
}
17-
})
18-
});
12+
Web components are converted to React components simply by passing them to the main react-integration function:
1913

20-
const ReactComponent = React.createClass({
21-
render () {
22-
return (
23-
<div>
24-
<custom-element>
25-
<div>
26-
<AnotherReactComponent />
27-
</div>
28-
</custom-element>
29-
</div>
30-
);
31-
}
32-
});
33-
```
14+
```js
15+
import reactify from 'skatejs-react-integration';
3416

35-
When `<custom-eleent>` removes its content, React loses track of the nodes it originally rendered and throws an error when the state changes.
17+
// Create your constructor.
18+
const MyComponent = class MyComponent extends HTMLElement {};
3619

37-
## How
20+
// Define your custom element.
21+
const CustomElement = window.customElements.define('my-component', MyComponent);
3822

39-
To get around this, we supply a function that will wrap the custom element in a React component that creates a new diff tree. This method is based on a React Training post by Ryan Florence about [Portals](https://github.com/ryanflorence/react-training/blob/gh-pages/lessons/05-wrapping-dom-libs.md#portals).
23+
// Reactify it!
24+
export default reactify(CustomElement);
25+
```
4026

41-
The convention is this:
27+
Usage with [SkateJS](https://github.com/skatejs/skatejs) is pretty much the same, Skate just makes defining your custom element easier:
4228

43-
- Call a function passing in your custom element constructor.
44-
- The React component passes the real DOM node of the new render tree to a property.
45-
- You do the rest.
29+
```js
30+
import reactify from 'skatejs-react-integration';
4631

32+
export default reactify(skate('my-component', {}));
33+
```
4734

48-
### Static example
35+
### Lexical scoping
4936

50-
The following example simply takes the `content` property value and renders it inside a div.
37+
When you convert a web component to a React component, it returns the React component. Therefore you can use it in your JSX just like any other React component.
5138

5239
```js
53-
import reactify from 'skatejs-react-integration';
40+
const ReactComponent = reactify(WebComponent);
41+
ReactDOM.render(<ReactComponent />, container);
42+
```
5443

55-
const CustomElement = skate('custom-element', {
56-
render: function (elem) {
57-
const div = document.createElement('div');
58-
div.appendChild(elem.content);
59-
elem.appendChild(div);
60-
}
61-
});
44+
### Custom events
6245

63-
export default reactify(CustomElement);
46+
Out of the box, React only works with built-in events. By using this integration layer, you can listen for custom events on a web component.
47+
48+
```js
49+
<MyComponent oncustomevent={handler} />
6450
```
6551

52+
Now when `customevent` is emitted from the web component, your `handler` will get triggered.
6653

67-
### Updating example
54+
### Web component properties
6855

69-
This will not update if the state changes, however. To do that we need to define a setter for the `content` property.
56+
When you pass down props to the web component, instead of setting attributes like React normally does for DOM elements, it will set all `props` as properties on your web component. This is useful because you can now pass complex data to your web components.
7057

7158
```js
72-
skate('custom-element', {
73-
properties: {
74-
content: {
75-
set (elem, data) {
76-
const container = elem.children[0];
77-
const reactTree = data.newValue;
78-
container.innerHTML = '';
79-
if (reactTree) {
80-
container.appendChild(reactTree);
81-
}
82-
}
83-
}
84-
},
85-
render: function (elem) {
86-
const div = document.createElement('div');
87-
div.appendChild(elem.content);
88-
elem.appendChild(div);
89-
}
90-
});
59+
<MyComponent items={[ 'item1', 'item2' ]} callback={function() {}} />
9160
```
9261

93-
You'll notice that since the diff tree ends in the ancestor tree of `<custom-element>` and the new tree begins at the React tree that was passed in to `content`, we are smashing the DOM at the `container` level. For smaller components this may not matter, but if your component is expecting updates then it'd be good to take accessibility and DOM performance into consideration.
62+
### Children
9463

64+
If your web component renders content to itself, make sure you're using Shadow DOM and that you render it to the shadow root. If you do this `children` and props get passed down as normal and React won't see your content in the shadow root.
9565

96-
### Diffing example
66+
### Injecting React and ReactDOM
9767

98-
In order to diff and patch the real DOM tree, we'll need something that can work with real DOM, not vDOM. In the next example we'll use [skatejs-dom-diff](https://github.com/skatejs/dom-diff).
68+
By default, the React integration will look for `React` and `ReactDOM` on the window. However, this isn't the case for all apps. If you're using ES2015 modules or CommonJS, you'll have to inject them into the reactify function as options:
9969

10070
```js
101-
skate('custom-element', {
102-
properties: {
103-
content: {
104-
set: skate.render
105-
}
106-
},
107-
render: skateDomDiff.render(function (elem) {
108-
const div = document.createElement('div');
109-
div.appendChild(elem.content);
110-
return div;
111-
})
71+
import reactify from 'skatejs-react-integration';
72+
import React from 'react';
73+
import ReactDOM from 'react-dom';
74+
75+
export default reactify(..., {
76+
React,
77+
ReactDOM
11278
});
11379
```
11480

115-
What's nice about using `skatejs-dom-diff` is that it also works with virtual DOM (or a mixture of both) and it comes with a light-weight virtual DOM interface bundled with it. If you wanted to use the previous example with JSX, all you'd need to do is the following.
81+
### Multiple React versions
11682

117-
```js
118-
skate('custom-element', {
119-
properties: {
120-
content: {
121-
set: skate.render
122-
}
123-
},
124-
render: skateDomDiff.render(function (elem, React) {
125-
return <div>{elem.content}</div>;
126-
})
127-
});
128-
```
83+
The integration sets a peer-dependency on React so you know what it's compatible with. That said, you still need to be mindful that the version of React you provide to the integration layer is correct.

0 commit comments

Comments
 (0)