react-to-can-webcomponent
converts React components to custom elements! It lets you share react components as native elements that don't require mounted being through React. The custom element acts as a wrapper for the underlying react component. Use these custom elements in any framework (vue, svelte, angular, ember, canjs) the same way you would use standard HTML elements.
react-to-can-webcomponent
:
- Works in all modern browsers. (Edge needs a customElements polyfill).
- Is
1.11KB
minified and gzipped.
Given a react component like:
class Greeting extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
Call reactToCanWebComponent
and customElements.define as follows:
import reactToCanWebComponent from "react-to-can-webcomponent";
const WebGreeting = reactToCanWebComponent(Greeting, React, ReactDOM);
customElements.define("web-greeting", WebGreeting);
Now you can use <web-greeting>
like any other HTML element!
You can create it programatically:
const webGreeting = document.createElement("web-greeting");
webGreeting.name = "StandardsFan";
document.body.append(webGreeting);
webGreeting.innerHTML //-> "<h1>Hello, StandardsFan</h1>"
Or you can use it declaratively:
document.body.innerHTML = "<web-greeting></web-greeting>";
document.body.firstChild.name = "CoolBeans";
document.body.firstChild.innerHTML //-> "<h1>Hello, CoolBeans</h1>"
By default, custom elements created by reactToCanWebComponent
only
pass properties to the underlying React component. To make attributes
work, you must specify your component's properties with
PropTypes as follows:
class Greeting extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
Greeting.propTypes = {
name: PropTypes.string.isRequired
};
Now reactToCanWebComponent
will know to look for name
attributes
as follows:
document.body.innerHTML = "<web-greeting name='Amazed'></web-greeting>";
document.body.firstChild.innerHTML //-> "<h1>Hello, Amazed</h1>"
To install from npm:
npm i react-to-can-webcomponent
reactToCanWebComponent(ReactComponent, React, ReactDOM)
takes the following:
ReactComponent
- A react component that you want to convert to a Web Component.React
- A version of React (or preact-compat) the component works with.ReactDOM
- A version of ReactDOM (or preact-compat) that the component works with.
A new class inheriting from HTMLElement
is
returned. This class can be directly passed to customElements.define
as follows:
customElements.define("web-greeting",
reactToCanWebComponent(Greeting, React, ReactDOM) );
Or the class can be defined and used later:
const WebGreeting = reactToCanWebComponent(Greeting, React, ReactDOM);
customElements.define("web-greeting", WebGreeting);
var myGreeting = new WebGreeting();
document.body.appendChild(myGreeting);
Or the class can be extended:
class WebGreeting extends reactToCanWebComponent(Greeting, React, ReactDOM)
{
disconnectedCallback(){
super.disconnectedCallback();
// special stuff
}
}
customElements.define("web-greeting", WebGreeting);
reactToCanWebComponent
creates a constructor function whose prototype is a Proxy. This acts as a trap for any property set on instances of the custom element. When a property is set, the proxy:
- re-renders the React component inside the custom element.
- creates an enumerable getter / setter on the instance to save the set value and avoid hitting the proxy in the future.
- sets up an observer to listen for observable properties that are read by the component. (Note: this is the only difference between this library and Bitovi's react-to-webcomponent library )
Also:
- Enumerable properties and values on the custom element are used as the
props
passed to the React component. - The React component is not rendered until the custom element is inserted into the page.