How to use Web Components in React
This tutorial teaches you how to use and interact with web components in React. We’ll build a small UI that adds people to a data grid.

Most Web Components, like the Vaadin component set, are distributed as ES modules. To use them efficiently, you need to have a project that handles them, like the one that is created with Create React App
If you already have an existing project that handles ES modules, feel free to skip directly to Step 1.
Step 0: Creating a project with Create React App
You’ll need to have Node 8.10.0 or later installed on your machine. Create a new project by running:
$ npx create-react-app webcomponents
$ cd webcomponents/
$ npm start
This creates the application and launches it. The start script opens up a browser automatically, pointing at http://localhost:3000/ where your app is now running.
Step 1: Install the polyfill
To start using Web Components in React, we need to have a polyfill installed for Web Component support in all browsers. We use the webcomponentsjs
polyfill. We also make use of vendor-copy
to make the polyfill available on runtime. Let’s start by installing them.
$ npm install --save @webcomponents/webcomponentsjs vendor-copy
Open package.json
to enable vendor-copy
. To the scripts
block, add a postinstall
which runs vendor-copy
after every time npm install
is invoked.
package.json
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject",
"postinstall": "vendor-copy" (1)
},
Add this row. Remember the comma on the previous row.
Next, at the end of the same file, give instructions to vendor-copy
on what it should copy over when the install is run. We need webcomponents-bundle.js
and custom-elements-es5-adapter.js
.
package.json
"vendorCopy": [
{
"from": "node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js",
"to": "public/vendor/custom-elements-es5-adapter.js"
},
{
"from": "node_modules/@webcomponents/webcomponentsjs/webcomponents-bundle.js",
"to": "public/vendor/webcomponents-bundle.js"
}
]
Now when you run npm install
within the root of the project, it will also trigger the postinstall and copy the polyfill.
Lastly, we have to use the polyfills in runtime by adding them to our index.html
. Add the following lines to the end of <body>
.
<script src="%PUBLIC_URL%/vendor/webcomponents-bundle.js"></script>
<script>if (!window.customElements) { document.write("<!--"); }</script>
<script src="%PUBLIC_URL%/vendor/custom-elements-es5-adapter.js"></script>
<!--! DO NOT REMOVE THIS COMMENT, WE NEED ITS CLOSING MARKER -->
Step 2: Add the web components to your UI
Now we have the support for the web components in place. Let’s continue by installing and adding some.
Install the components
We will start off by installing the components. In this case, we install vaadin-text-field
, vaadin-button
, and vaadin-grid
from the Vaadin component set.
$ npm install --save @vaadin/vaadin-text-field @vaadin/vaadin-button @vaadin/vaadin-grid
Once the install finishes, import the components in App.js
to make them available to your browser.
src/App.js
import '@vaadin/vaadin-button';
import '@vaadin/vaadin-grid';
import '@vaadin/vaadin-text-field';
Use Web Components to build the UI
You can now use the Web Components like any other HTML tag. Replace the contents of the render()
method in App.js
with the following:
src/App.js
render() {
return (
<div className="App">
<div className="form">
<vaadin-text-field label="First Name" ref="firstName" />
<vaadin-text-field label="Last Name" ref="lastName" />
<vaadin-button ref="addButton"> Add </vaadin-button>
</div>
<vaadin-grid ref="grid">
<vaadin-grid-column path="firstName" header="First name" /> (1)
<vaadin-grid-column path="lastName" header="Last name" />
</vaadin-grid>
</div>
);
}
The grid uses an array of objects as its data source. The
path
attribute defines what property of that object should be shown in the column.
Notice that we added ref
attributes for all components. This enables us to reference the components from JavaScript in the next step.
Listen for events and update properties
Now that we have all the UI building blocks in place, the next step is to add some functionality.
Start by adding a componentDidMount()
function to App.js
. It will be run after the templated has been loaded. A fair amount is going on in this function, so let’s look at what’s going on step by step:
src/App.js
componentDidMount() {
let people = []; (1)
this.refs.addButton.addEventListener('click', e => { (2)
people = [ (3)
...people,
{
firstName: this.refs.firstName.value,
lastName: this.refs.lastName.value
}
];
this.refs.grid.items = people; (4)
this.refs.firstName.value = ''; (5)
this.refs.lastName.value = '';
});
}
Define an array to hold the people that are added.
Get references to the components with
this.refs
. Add aclick
listener on the button for adding people.Create a new array with all previous people and a newly created person. The name values can be retrieved from the
value
property on the components.Set the new
people
array as the items property on the grid to display the updated data.Clear the input fields.
Finally, update the styles in App.css
to the following:
src/App.css
.App {
padding: 4px;
}
.App .form * {
margin-right: 4px;
}
Run the application, and you should now be able to add new entries to the grid.
Summary and next steps
Web Components behave like any other HTML element once you have imported them. You can set and read attributes and properties for data, and listen to events to add interactivity.
Web Components are designed to be framework independent. You can use them together with a framework or templating library to cut down on the boilerplate of manually querying elements and setting their values. See any of our other guides on using Web Components in popular frameworks for further information.
You can read more about web component framework compatibility on custom-elements-everywhere.com.
Comments (8)