https://github.com/alesgenova/stenciljs-in-react
Stenciljs components in React: step by step guide
https://github.com/alesgenova/stenciljs-in-react
reactjs stenciljs webcomponents
Last synced: about 1 year ago
JSON representation
Stenciljs components in React: step by step guide
- Host: GitHub
- URL: https://github.com/alesgenova/stenciljs-in-react
- Owner: alesgenova
- Created: 2018-06-17T21:00:16.000Z (almost 8 years ago)
- Default Branch: master
- Last Pushed: 2018-11-08T02:42:42.000Z (over 7 years ago)
- Last Synced: 2025-04-03T23:32:52.232Z (about 1 year ago)
- Topics: reactjs, stenciljs, webcomponents
- Language: JavaScript
- Homepage:
- Size: 15.6 KB
- Stars: 19
- Watchers: 3
- Forks: 3
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Stencil components in React
[Stencil](https://stenciljs.com/) is not a JS framework. It is a compiler that produces a reusable web component that can be embedded anywhere else.
This is a step by step guide to consume a non-trivial stencil component in a [React](https://reactjs.org/) app.
The starter react app was created with [create-react-app](https://github.com/facebook/create-react-app).
## Similar guides
- [Stencil components in Vue](https://github.com/alesgenova/stenciljs-in-vue.git)
- [Stencil components in Angular](https://github.com/alesgenova/stenciljs-in-angular.git)
## Table of contents
- [Add the component(s) to the dependencies](#1-add-the-components-to-the-dependencies)
- [Import the component](#2-import-the-components)
- [Consume the component](#3-consume-the-component)
- [Appendix: Attribute vs Prop](#appendix-attribute-vs-prop)
## 0: Build a stenciljs component and publish it to npm
Creating your first stencil component is very easy and it is well documented [here](https://stenciljs.com/docs/my-first-component).
This example will consume two components:
- [@openchemistry/molecule-vtkjs](https://github.com/OpenChemistry/oc-web-components/tree/master/packages/molecule-vtkjs) : To display molecular structures
- [split-me](https://github.com/alesgenova/split-me) : To create resizable split layouts
## 1: Add the component(s) to the dependencies
Add the component to the app dependencies in `package.json`
```json
// package.json
"dependencies": {
...
"@openchemistry/molecule-vtkjs": "^0.3.2",
"split-me": "^1.1.4"
}
```
## 2: Import the component(s)
Import the component in the `index.js` of the app:
```js
import { defineCustomElements as defineMolecule } from '@openchemistry/molecule-vtkjs/dist/loader';
import { defineCustomElements as defineSplitMe } from 'split-me/dist/loader';
defineMolecule(window);
defineSplitMe(window);
```
## 3: Consume the component
It is now possible to use the tag provided by the stencil component in the `render` function of any react component.
```jsx
render() {
return (
)
}
```
## Appendix: Attribute vs Prop
`oc-molecule-vtkjs` has a property named `cjson` that expects an object (or a JSON.stringified object).
Strings and numbers can be passed directly as attributes to a stencil component.
One way to pass a complex object to a component could be to `JSON.stringify()` the object and then `JSON.parse()` it inside the component. But this round trip can be expensive, and it would be a good idea to pass the object directly as a prop.
React doesn't provide a convenient way to distinguish between attribute and prop, so a little work is needed to achieve this.
It just boils down to saving a reference to the element of the stencil component, and then set the property directly in the javascript code.
To make this operation easier, it can be convenient to create a reusable utility function [`wc`](https://github.com/ionic-team/ionic-react-conference-app/blob/master/src/utils/stencil.js).
```js
export function wc(customEvents = {}, props = {}) {
let storedEl;
return function (el) {
for (let name in customEvents) {
let value = customEvents[name] ;
// If we have an element then add event listeners
// otherwise remove the event listener
const action = (el) ? el.addEventListener : storedEl.removeEventListener;
if (typeof value === 'function') {
action(name, value);
return;
}
}
// If we have an element then set props
if (el) {
for (let name in props) {
let value = props[name] ;
el[name] = value;
}
}
storedEl = el;
};
}
```
And then use it in the `jsx` to bind events and properties to the webcomponent this way:
```jsx
import React, { Component } from 'react';
import { wc } from './utils/webcomponent';
class SomeComponent extends Component {
render() {
return (
);
}
}
export default SomeComponent;
```