https://github.com/frigus02/react-custom-element-wrapper
Use Custom Elements with properties or events in React
https://github.com/frigus02/react-custom-element-wrapper
Last synced: 3 days ago
JSON representation
Use Custom Elements with properties or events in React
- Host: GitHub
- URL: https://github.com/frigus02/react-custom-element-wrapper
- Owner: frigus02
- License: mit
- Created: 2019-04-03T18:47:49.000Z (over 7 years ago)
- Default Branch: master
- Last Pushed: 2019-04-03T19:59:46.000Z (over 7 years ago)
- Last Synced: 2025-10-09T10:38:11.831Z (10 months ago)
- Language: TypeScript
- Homepage: https://www.npmjs.com/package/react-custom-element-wrapper
- Size: 12.7 KB
- Stars: 1
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
Awesome Lists containing this project
README
# React Custom Element Wrapper
[](https://www.npmjs.com/package/react-custom-element-wrapper)
Use Custom Elements with properties or events in React.
[Custom Elements](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements) can define their API with attributes, properties, events and children (slots). React supports attributes and children out of the box. But there are some challenges with the rest:
- Properties don't work because React calls `setAttribute` on custom elements.
- Events don't work because React has [synthetic events](https://reactjs.org/docs/events.html), which don't support custom DOM events.
People are working on a solution (see [React RFC about custom element support](https://github.com/reactjs/rfcs/pull/15)). But we can already use a workaround using [refs](https://reactjs.org/docs/refs-and-the-dom.html) now. This library is a tiny wrapper you can put around any custom element to make it work in React.
Note: If the custom element you want to use only uses attributes and children, you don't have to use this wrapper. Just use the custom element directly.
## Table of Contents
- [Install](#install)
- [Usage](#usage)
- [PropTypes](#proptypes)
- [TypeScript](#typescript)
- [Contributing](#contributing)
- [License](#license)
## Install
```sh
# npm
npm install react-custom-element-wrapper
# yarn
yarn add react-custom-element-wrapper
```
## Usage
Create a wrapper around your custom element.
```js
import customElement from "react-custom-element-wrapper";
// Load Custom Element JavaScript
import "my-greeting";
// Define React props and how they match to the elements attributes, properties and events
const MyGreeting = customElement("my-greeting", {
salutation: { type: "attribute", name: "salutation" },
traits: { type: "property", name: "traits" },
onWave: { type: "event", name: "wave" },
});
export default MyGreeting;
```
Then use the wrapper in the same way as any other React component.
```js
import MyGreeting from "./MyGreeting";
const App = () => (
Bear
);
```
## PropTypes
Components generated using this library automatically get these basic [prop-types](https://github.com/facebook/prop-types):
- Attributes: `PropTypes.string`
- Properties: `PropTypes.any`
- Events: `PropTypes.function`
## TypeScript
You can type elements generated using this library by defining a type for the React props. When doing so, your types have to match a certain schema:
- Attributes can only be mapped to a prop of type `string`.
- Properties can be mapped to anything.
- Events can only be mapped to a [`EventListenerOrEventListenerObject`](https://github.com/Microsoft/TypeScript/blob/8a19e4bcf95de764ca18bc0276697ab86bd783e4/lib/lib.dom.d.ts#L17493). You probably want to use something like `CustomElement => void`. And if the custom element provides a typed event object, you can use that instead.
```ts
import customElement from "react-custom-element-wrapper";
import "my-greeting";
// Define React props
type Props = {
salutation: string,
traits: string[],
onWave: CustomEvent => void
};
const MyGreeting = customElement("my-greeting", {
salutation: { type: "attribute", name: "salutation" },
traits: { type: "property", name: "traits" },
onWave: { type: "event", name: "wave" },
});
export default MyGreeting;
```
## Contributing
Please see [CONTRIBUTING.md](CONTRIBUTING.md).
## License
[MIT](LICENSE)