Stencil components in React
Stencil 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 app.
The starter react app was created with create-react-app.
Similar guides
Table of contents
- Add the component(s) to the dependencies
- Import the component
- Consume the component
- 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.
This example will consume two components:
- @openchemistry/molecule-vtkjs : To display molecular structures
- 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
// package.json "dependencies":
2: Import the component(s)
Import the component in the index.js
of the app:
;; ;;
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.
{ return <split ="2"> <oc ="0"></oc-molecule-vtkjs> <oc ="1"></oc-molecule-vtkjs> </split-me> }
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
.
{ let storedEl; return { for let name in customEvents let value = customEventsname ; // If we have an element then add event listeners // otherwise remove the event listener const action = el ? eladdEventListener : storedElremoveEventListener; if typeof value === 'function' ; return; // If we have an element then set props if el for let name in props let value = propsname ; elname = value; storedEl = el; };}
And then use it in the jsx
to bind events and properties to the webcomponent this way:
import React Component from 'react';import wc from './utils/webcomponent'; { return <div => <oc = /> </div> ; } ;