React vs. web components

7 min read 2012

react vs web components

In this article, we will be discussing web components and React. Before moving ahead, one thing to note here is that React and web components serve different purposes. Web components allow us to write reusable and strongly encapsulated custom elements. React, however, is a declarative JavaScript library that addresses state management problems in UI development. Today, we will cover types of components, libraries provided for styling in React and web components, and their accessibility.

Components

As already explained, we can write reusable UI elements with web components. But you might think that we could do the same using React as well, for example, we can create a component and reuse it somewhere else in the project. Here is the difference, a React component can only be reused in the React application. A web component, on the other hand, can be used anywhere. It can be used in React, Angular, or Vue, etc., as it is included in the HTML specification and is native. For example, a custom header element created using web components can be used across various libraries and frameworks.

With that being discussed, let’s talk about the types of components provided by both of them.

Types of web components

There are three types of web components.

Custom element

With custom elements, we can create a new customized HTML tag. It uses the browser’s JavaScript API customElements.define() method to do that. A custom element is a JavaScript class that extends HTMLElement. Moreover, custom elements require a hyphen in their names so the HTML parser can recognize them. Consider the following example:

<!DOCTYPE html>
<html>
<head>
<title>Custom Element</title>
</head>
<body>
<div>
<h1>Custom Element</h1>
<test-element></test-element>
</div>

<script type="text/javascript">
class TestElement extends HTMLElement{
constructor() {
  super();
  this.setAttribute('name', 'ashton'); //setting an attribute

}
connectedCallback() {
    this.innerHTML = `<div><p>Hello ${this.getAttribute('name')}!</p><p>Nice to meet you</p></div>`;
  }
}
//register the custom element
customElements.define('test-element', TestElement);
</script>
</body>
</html>

Output:

custom element

Shadow DOM

It allows you to create an isolated component, i.e document.querySelector() won’t return nodes defined in a shadow DOM. Moreover, styles defined in the shadow DOM are contained to it, for example, scoped CSS. If you change the background color of a div to blue in a shadow DOM, then that div’s background will get changed only, and no divs outside of it will be affected:

<!DOCTYPE html>
<html>
<head>
<title>Custom Element</title>
</head>
<body>
<div>
<h1>Custom Element</h1>
<test-element></test-element>
</div>

<script type="text/javascript">
class TestElement extends HTMLElement{
constructor() {
  super();
  this.setAttribute('name', 'ashton'); //setting an attribute
  const shadowRoot = this.attachShadow({mode: 'open'}); //attaches a shadow DOM tree to <test-element> and returns a reference

}
connectedCallback() {
    this.shadowRoot.innerHTML = `<style>
     div {
     background:cyan;
     }
    </style>
    <div><p>Hello ${this.getAttribute("name")}!</p><p>Nice to meet you</p></div>`;
  }
}
//register the custom element
customElements.define('test-element', TestElement);
</script>
</body>
</html>

Output:

blue background added to custom element

Templates

Templates allow us to declare markup structures at the load time using the <template> tag. This element and its content will not render until we get its reference and attach it to the DOM manually. It allows us to add dynamic data. Therefore, if we have to use some markup structure at various times, we can use templates and avoid repeating the same code:

<!DOCTYPE html>
<html>
<head>
<title>Custom Element</title>
</head>
<body>
<div>
<h1>Custom Element</h1>
<template id="student_template">
<style>
    li {
      color:cyan;
      list-style: none;
    }
  </style>
<li>
    <span class="name"></span> &mdash;
    <span class="score"></span>
</li>
</template>
<test-element></test-element>
<ul id="students"></ul>
</div>

<script type="text/javascript">
class TestElement extends HTMLElement{
constructor() {
  super()
  const shadowRoot = this.attachShadow({ mode: "open" });

}
connectedCallback() {
let students = [
{name: "Emma", score: 90},
{name: "Ashton", score: 70},
{name: "Hannah", score: 85},
{name: "Steve", score: 90},
{name: "Amy", score: 75},
]

    students.forEach(student=>{
    let template = document.getElementById("student_template");
    let templateContent = template.content.cloneNode(true);
    this.shadowRoot.appendChild(templateContent); //append a clone of the template content to the shadow root

    this.shadowRoot.querySelector('.name').innerHTML = student.name //add the name
    this.shadowRoot.querySelector('.score').innerHTML = student.score //add the score


    document.getElementById("students").appendChild(this.shadowRoot) //append the list to the ul students
    })
  }
}
//register the custom element
customElements.define('test-element', TestElement);
</script>
</body>
</html>

Output:

custom element with template tag

We made a custom demo for .
No really. Click here to check it out.

React components

There are two main types of React components.

Class components

A class component is simply a JS class that extends the React.Component class. It takes props, manages the state of a component, and returns the JSX code through the render function. Props contain the data passed from the parent component. The component’s data can be stored in the state object. Whenever the state changes, the component rerenders. It also contains lifecycle methods that run at different points from the creation of the components until it gets destroyed. For example, constructor() is the first method that gets called when a component’s instance gets initiated, and therefore the state is initialized here.

Let’s see an example:

import React from 'react';
import './style.css';

class MyComponent extends React.Component {

  constructor(props) {
    super(props);

    this.state = {
        value:"Touch me"
    };
  }
  buttonHandler=()=>{
    if (this.state.value=="Touch me"){
      this.setState({value:'Touched!'})
    }
    else {
      this.setState({value:'Touch me'})
    }
  }
  render() {
    return(
      <div>
          <h1>My Component!</h1>
          <button onClick={this.buttonHandler} className="button">{this.state.value}</button>
      </div>
    );
  }
}
export default MyComponent;

my component button

When the button is pressed:

button reads "touched!"

Functional components

Simply put, a functional component is a JavaScript function that returns the JSX code. Previously, functional components were purely presentational components because they did not have support for state management. However, with React Hooks, we can now have state and lifecycle methods as well.

Let’s do the above example using a functional component:

import React, {useState} from 'react';
import './style.css';

const MyComponent = (props) =>{
    const [value, setValue] = useState("Touch me"); //creating a state using the useState hook

    const buttonHandler=()=>{
    if (value=="Touch me"){
      setValue("Touched!") //set the value to Touched! if it is Touch me, changing state
    }
    else {
      setValue("Touch me") //changing state
    }
    }

    return (
      <div>
          <h1>My Component!</h1>
          <button onClick={buttonHandler} className="button">{value}</button>
      </div>
    )


}
export default MyComponent;

functional component button
When the button is pressed:
functional component with touched button

Styling

When it comes to building components, UI is a big part of it. You always want to create beautiful, engaging, and user-friendly components. However, styling it yourself from scratch can be a bit tedious and time-consuming process. Moreover, in React, it gets more difficult because it does not have a scoped style like web components do. So, you always look for external modules that can do that work for you.

React has a large ecosystem. Therefore, it has many styling libraries and frameworks compared to web components.

React

Material-UI

It is one of the most popular UI frameworks in React. It is created and maintained by Google. It provides several UI components, styles, themes, layouts, and icons, etc. It is very versatile, and continuous work and effort are being put in to keep improving it. Its latest stable version is v4.11.1 as of December 2020.

React Bootstrap

React Bootstrap is another popular React UI framework that replaces the Bootstrap JavaScript and has Bootstrap at its core. It provides various components, theming support, layouts, etc. It also has a large, growing team, and its latest version is v1.4.0 that supports Bootstrap 4.5.

Semantic UI React

It is the React integration for the Semantic UI. It provides many cool custom elements, for example, Button, Container, Loader, and Input, etc. It has the same styling system and theming as the Semantic UI. So, if you know it, you do not need to learn anything new. Moreover, it has sub-components that allow us to access the underlying markup, and because of that, we get flexibility in customizing elements.

Web components

Material Web Components

This is the web component version of the Material-UI framework. However, it is still a work in progress. Its latest version is v0.20.0, and major changes are expected until the 1.0 release.

Bootstrap in web components

There are modules available that allow you to use Bootstrap in your web components. However, some are still unstable or under development, and others do not provide as many features as React-Bootstrap does. For example, bootstrap-webcomponents is a rewrite of bootstrap for web components, but it is still in the development mode. Aybolit Bootstrap provides a set of web components that are inspired by Bootstrap, but it does not have a wide range of components and features.

Elix

It is an open collection of ready-to-use web components for common UI patterns, such as carousels, buttons, and menus, etc. It also gives you the flexibility to customize them or even create new elements based on existing Elix’s components.

Accessibility (a11y)

When we talk about the accessibility of a website, we mean that it can easily be used by everyone. If our website is created with React or web components, then these components need to be accessible. So, the question arises, are they?

React allows us to create websites that are completely accessible. It can often be done using standard HTML techniques. For example, we can use the aria-* attributes in JSX in the same way we use them in plain HTML, i.e., they do not need to be camelCased. In React, we add an extra div to wrap all elements, but it will break HTML semantics, won’t it? Well, it does, but we can easily solve this problem by using the <React.Fragment> tag.

Another aspect of accessibility is that the application should be able to be used with the keyboard only. Now, React continuously changes the HTML DOM during runtime, and because of that, the keyboard focus can get lost. However, we can programmatically set the focus in various lifecycle methods of the component. Furthermore, we can change titles whenever the screen (component) changes using the react-document-title.

Web components are also accessible because a custom element can extend any native HTML element, and thus, it inherits all of its characteristics, including accessibility features. Moreover, there can be a misunderstanding that elements created inside a shadow DOM won’t be accessible. However, this is not the case, and screen readers can easily access the content.

That’s it for this article. The differences are summarized in the table below.

React Web components
It is a JavaScript library for building UI interfaces for single-page applications. It is a set of different technologies that allow us to create reusable and isolated elements.
Types of components include functional and class. Types of components include custom elements, shadow DOM, and templates.
Component re-rendering based on state changes. No state management.
Components are reusable in React only. Interoperable.
No local styling. CSS can be scoped using shadow DOMs.
React provides a unidirectional data flow pattern. You have to implement data binding yourself.
Its ecosystem is incredibly vast and powerful. It has a large community and forever growing tools and libraries. The ecosystem is not as vast as React’s ecosystem.

 

Full visibility into production React apps

Debugging React applications can be difficult, especially when users experience issues that are hard to reproduce. If you’re interested in monitoring and tracking Redux state, automatically surfacing JavaScript errors, and tracking slow network requests and component load time, try LogRocket.

LogRocket is like a DVR for web apps, recording literally everything that happens on your React app. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred. LogRocket also monitors your app's performance, reporting with metrics like client CPU load, client memory usage, and more.

The LogRocket Redux middleware package adds an extra layer of visibility into your user sessions. LogRocket logs all actions and state from your Redux stores.

Modernize how you debug your React apps — .

6 Replies to “React vs. web components”

  1. You forgot to say we can pass easily data to react components while it is hard to do for webComponents. Only primitive arguments are supported and it is a pain to pass functions, objects or class instances.

  2. -Types of (React) components include functional and class. That’s not two types, but two ways of doing the same.
    -Types of (web) components include custom elements, shadow DOM, and templates. Shadow DOM it’s a property of custom elements and templates are not part of web components at all.
    -Components are reusable in React only. As long as they may be compiled as web components itself, how it’s this possible? I’m even using React components in Angular (without WC build).
    -The ecosystem is not as vast as React’s ecosystem. How can a Web standard not have a good ecosystem?
    -(React) It is a JavaScript library for building UI interfaces for single-page applications. That’s what it was intended to be, but people build entire SPAs with it, not just UI.
    -It is a set of different technologies that allow us to create reusable and isolated elements. It’s not a set of technologies, as it’s a Web standard and JavaScript is the only technology used. (Of course there are options that allow you to use more comfortable alternatives, like stencil, lit-element…)

  3. You can package the entire react componen as a JS lib and reuse in any App. Good ir bad idea… But you can do It.

  4. You are wrong here I am afraid. Web components have a JS interface which allows properties and any other complex argument to be passed.

    Many wc helper libraries like lit-element also provide convenience mechanisms to do this in just the same way you would in react.

Leave a Reply