react-to-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-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 reactToWebComponent
and customElements.define as follows:
import reactToWebComponent from "react-to-webcomponent";
const WebGreeting = reactToWebComponent(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 reactToWebComponent
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 reactToWebComponent
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-webcomponent
https://unpkg.com/react-to-webcomponent/dist/react-to-webcomponent.js
reactToWebComponent(ReactComponent, React, ReactDOM, options)
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.options
- An optional set of parameters.options.shadow
- Use shadow DOM rather than light DOM.options.dashStyleAttributes
- convert dashed-attirbutes on the web component into camelCase props for the react component
A new class inheriting from HTMLElement
is
returned. This class can be directly passed to customElements.define
as follows:
customElements.define("web-greeting",
reactToWebComponent(Greeting, React, ReactDOM) );
Or the class can be defined and used later:
const WebGreeting = reactToWebComponent(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 reactToWebComponent(Greeting, React, ReactDOM)
{
disconnectedCallback(){
super.disconnectedCallback();
// special stuff
}
}
customElements.define("web-greeting", WebGreeting);
Components can also be implemented using shadow DOM.
const WebGreeting = reactToWebComponent(Greeting, React, ReactDOM, { shadow: true });
customElements.define("web-greeting", WebGreeting);
var myGreeting = new WebGreeting();
document.body.appendChild(myGreeting);
var shadowContent = myGreeting.shadowRoot.children[0];
Using dashStyleAttributes to convert dashed-attributes into camelCase react props
class Greeting extends React.Component {
render () { return <h1>Hello, { this.props.camelCaseName }</h1>; }
}
Greeting.propTypes = {
camelCaseName: PropTypes.string.isRequired
};
customElements.define(
"my-dashed-style-greeting",
reactToWebComponent(Greeting, React, ReactDOM, { dashStyleAttributes: true })
);
document.body.innerHTML = "<my-dashed-style-greeting camel-case-name='Christopher'></my-dashed-style-greetingg>";
console.log(document.body.firstElementChild.innerHTML) // "<h1>Hello, Christopher</h1>"
reactToWebComponent
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.
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.