Security News
Fluent Assertions Faces Backlash After Abandoning Open Source Licensing
Fluent Assertions is facing backlash after dropping the Apache license for a commercial model, leaving users blindsided and questioning contributor rights.
react-html-element
Advanced tools
An HTMLElement extension that provides a simple setup for Web Components using React.
The React documentation around using React in 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. Namely, complex React apps rendered in Web Components lose their functionality.
react-html-element
seamlessly creates the glue needed to utilize React in your Web Components without losing functionality.
To install, simply run:
npm install --save react-html-element
Here is a simple example React App (using Typescript):
function Incrementer(): React.ReactElement {
const [increment, setIncrement] = useState(0);
return (
<>
<button
id="iterate-button"
type="button"
onClick={(): void => setIncrement(prevIncrement => prevIncrement + 1)}
>
Increment
</button>
<div data-testid="current-increment">{increment}</div>
</>
);
}
To utilize Incrementer
as a Web Component, we'll use react-html-element
:
import React, { useState, useEffect } from 'react';
import ReactDOM from 'react-dom';
import ReactHTMLElement from 'react-html-element';
class IncrementerComponent extends ReactHTMLElement {
connectedCallback(): void {
ReactDOM.render(<Incrementer />, this.mountPoint);
}
}
customElements.define('incrementer', ReactTestComponent);
The key pieces of code are ... extends ReactHTMLElement
and this.mountPoint
.
Polyfills
One thing to remember is that you will need to load the webcomponentsjs polyfills for
ReactHTMLElement
to work in all browsers. Be sure to include the ES5 adapter, as we currently transpileReactHTMLElement
down to ES5. The polyfills should be in the<head>
, and should look something like this:
<script src="https://cdnjs.cloudflare.com/ajax/libs/webcomponentsjs/2.4.3/webcomponents-bundle.js"></script> <script> if (!window.customElements) { document.write('<!--'); } </script> <script src="https://cdnjs.cloudflare.com/ajax/libs/webcomponentsjs/2.4.3/custom-elements-es5-adapter.js"></script> <!--- We use the closing bracket of this comment to close off the above opening comment, if it gets written -->
There are many ways to implement these polyfills, and you can explore them in the webpcomponentsjs README.
This will allow us to utilize our Web Component as an element in any HTML:
<html>
<head>
<title>Incrementer Example</title>
<!-- Load the polyfills -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/webcomponentsjs/2.4.3/webcomponents-bundle.js"></script>
<script>
if (!window.customElements) {
document.write('<!--');
}
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/webcomponentsjs/2.4.3/custom-elements-es5-adapter.js"></script>
<!--- We use the closing bracket of this comment to close off the above opening comment, if it gets written -->
<!-- load your web component -->
<script src="./path/to/incrementer.js"></script>
</head>
<body>
<h1>
Behold: An Incrementer
</h1>
<!-- put your web component in your html -->
<incrementer></incrementer>
</body>
</html>
this.mountPoint
is a getter that establishes the Shadow DOM for your Web Component and provides a DOM element to mount to. By default, this is just a div
, but you can utilize a template and target a specific mount position within it by passing the template and a CSS selector into ReactHTMLElement
's constructor. Our example from above would look like this, with a custom template and mount point:
import React, { useState, useEffect } from 'react';
import ReactDOM from 'react-dom';
import ReactHTMLElement from 'react-html-element';
class IncrementerComponent extends ReactHTMLElement {
connectedCallback(): void {
ReactDOM.render(<Incrementer />, this.mountPoint);
}
constructor(): void {
super(
// The first parameter is your template.
"<h2>I am the incrementer</h2><article id="react-mount"><article>",
// The second parameter is the CSS selector for your mount point.
"#react-mount"
)
}
}
customElements.define('incrementer', ReactTestComponent);
Using styled-components with ReactHTMLElement seems tricky, but there's actually a very simple way to implement it: the StyleSheetManager
. An app rendered with StyleSheetManager
might look like this:
class ReactWebComponent extends ReactHTMLElement {
connectedCallback() {
ReactDOM.render((
<StyleSheetManager target={this.mountPoint.parentNode}>
<App />
</StyleSheetManager>
), this.mountPoint);
}
}
We use this.mountPoint.parentNode
for the styles instead of simply using this.mountPoint
for the case 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 parentNode
will cause the styles to be placed within the Shadow DOM, but not inside the same component where our app is mounted.
If you're using a custom template, you can find a node for your StyleSheetManager
target by searching through the shadowRoot
in the same way you might search through document.body
. Often, simply using this.mountPoint.parentNode
will still work as expected, even with custom templates.
This package uses semantic-release
. Changes will be compiled into a changelog and the package versioned, tagged and published automatically.
Please ensure your commit messages adhere to the following structure:
<type>: <subject>
<BLANK LINE>
<body>
Only the header is mandatory. The supported types are based off of the ESLint Convention.
FAQs
An HTMLElement extension that provides a simple setup for Web Components using React.
The npm package react-html-element receives a total of 555 weekly downloads. As such, react-html-element popularity was classified as not popular.
We found that react-html-element demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 4 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Fluent Assertions is facing backlash after dropping the Apache license for a commercial model, leaving users blindsided and questioning contributor rights.
Research
Security News
Socket researchers uncover the risks of a malicious Python package targeting Discord developers.
Security News
The UK is proposing a bold ban on ransomware payments by public entities to disrupt cybercrime, protect critical services, and lead global cybersecurity efforts.