Web Component: Why You Should Stick to React

Nathan Sebhastian
Bits and Pieces
Published in
7 min readSep 16, 2020

--

There’s an interesting discussion on the Internet about how Web Components will replace modern front-end libraries, and that popular tools like React and Vue will slowly become obsolete like MooTools and jQuery.

Maybe you want to use React for your web application projects, but fear that it’s going to be replaced by Web Components. This article will help you alleviate that fear by learning the difference between Web Components and React.

The purpose of Web Components

Web Components is a set of different technologies that are used together to help developers write UI elements that are semantic, reusable, and properly isolated.

  • A custom element is a way of defining an HTML element by using the browser’s JavaScript API. A custom element has its own semantic tag and lifecycle methods, similar to a React component
  • Shadow DOM is a way of isolating DOM elements and scoping CSS locally to prevent breaking changes from affecting other elements.
  • HTML template is a way of writing invisible HTML elements that acts as a template that you can operate on using JavaScript’s query selector.

Let’s learn how each of these technology actually works with code examples.

A custom element example

Web Component’s custom elements are created by using the browser’s JavaScript API. A custom element is defined using JavaScript’s class keyword that extends HTMLElement. Once defined, the custom element can be reused as many times as you need in your application:

A custom element name must include a dash or the browser will complain that you have an invalid element name. You need to name a button as <primary-button> or <button-component> instead of just <button>.

Custom elements also have lifecycle callbacks for running code during specific times of its existence. These lifecycle callbacks work in a similar way to React’s lifecycle methods.

As of today, you need to write custom elements

The shadow DOM example

Shadow DOM allows you to write HTML elements that were scoped from the actual DOM tree. It’s attached to the parent element, but won’t be considered as its child element by the browser. Here is an example:

Any code you write inside the shadow DOM will be encapsulated from the code outside of it. One of the benefits of using shadow DOM is that any CSS code you write will be local and won’t affect any element outside of it.

When you inspect the shadow element, you’ll see it marked with #shadow-root:

The browser will return null when you try to select the shadow button with document.getElementById(‘shadow-button’) . You need to select the parent element and grab its shadowRoot object first:

const el = document.getElementById('example').shadowRoot
el.getElementById('shadow-button')

HTML template example

HTML template allows you to write invisible HTML elements that you can iterate through with JavaScript in order to display dynamic data. To write one, you need to wrap the elements inside a <template> tag:

<template id="people-template">
<li>
<span class="name"></span> &mdash;
<span class="age"></span>
</li>
</template>
<ul id="people"></ul>

Then you can iterate through the template above with JavaScript selector and append it into the <ul> element :

const fragment = document.getElementById('people-template');
const people = [
{ name: 'Daniel', age: 22 },
{ name: 'Jessie', age: 29 },
{ name: 'Andy', age: 32 }
];
people.forEach(person => {
const instance = document.importNode(fragment.content, true);

instance.querySelector('.name').innerHTML = person.name;
instance.querySelector('.age').innerHTML = person.age;

document.getElementById('people').appendChild(instance);
});

By using the template, you can fetch data from an API server and use the template to serve the data in a structured way.

Now that you know what and how Web Components work, it’s time to answer the question.

Will Web Components replace React?

A modern front-end application needs more than just components. The great thing about React is that it keeps your components in sync with your data.

When compared with Web Components, React has the following advantages:

  • Allows you to change the underlying data model with state
  • Trigger UI changes based on the state
  • Writing components using functions and hooks
  • A ready-to-use unidirectional data flow
  • A greater ecosystem of third-party libraries and guides

💡 Note: As an aside, you don’t always have to make a choice between either Web Components or React. You can incorporate Web Components built with Lit or Stencil into existing modular React apps, and store, version, document, and test them together using Bit.

Bit comes with a fully featured component development environment for Lit and Stencil, with proper tools, automatic dependency management, a runtime environment, and more for your Web Components.

React’s eco-system is incredibly vast — so much so that it is now possible to use React for everything: Dynamic SPAs, Static pages, Native Android/iOS apps, Windows/Mac desktop apps, CLI apps, etc.

That means two things:

  1. You can learn once and build for multiple platforms
  2. You can build once and reuse across different apps

Sharing components (and reusing them across apps) is now easier than ever with tools like Bit (Github) that allow you to track components independently and share them, from any project, to a single component hub.

Exploring shared React components on Bit.dev

React’s underlying data model with state and props allows its components to change the rendered elements on the screen without imperatively manipulating the DOM or changing attributes manually. When you change the state, React will automatically re-render the components to trigger UI changes.

React also allows you to write components using functions and hooks. When it first came out, hooks are a big improvement to React because it reduces the complexity of managing a component’s lifecycle. It also enables you to write stateful components using functions, completely removing the need to use classes, which confuses both people and machines.

Furthermore, functional components in React are easier to maintain because of the way useEffect hook gather related logic under one function. For example, when using class components in React, you need to duplicate your code to run on mount and subsequent updates:

class Example extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
}
componentDidMount() {
document.title = `You clicked ${this.state.count} times`;
}
componentDidUpdate() {
document.title = `You clicked ${this.state.count} times`;
}
render() {
return (
<div>
<p>You clicked {this.state.count} times</p>
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Click me
</button>
</div>
);
}
}

But with hooks, you can have a useEffect function that runs on mount and subsequent updates in a single function:

import React, { useState, useEffect } from 'react';function Example() {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `You clicked ${count} times`;
});
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}

When using class components, you need to group unrelated code under the same lifecycle method because that’s the only place where you can run the code reasonably, such as fetching data and setting up listener on componentDidMount:

componentDidMount() {
// Putting data fetching and listener in the same function
axios.post();
DataSource.addChangeListener(this.handleChange);
}

With useEffect hook, you can separate this unrelated code but run them on the same lifecycle:

// separating functions to minimize confusionuseEffect(() => {
axios.post();
});
useEffect(() => {
DataSource.addChangeListener(this.handleChange);
});

As a library for building complete web applications, React also offers a unidirectional data flow pattern, where data is passed down from parent components to children components with props. Web Components currently requires you to write your own data binding pattern.

Finally, React has a big collection of third party libraries to help developers with the most common application features like:

Of course, Web Components may replace React when there is enough support for all of these development needs, but I’m certain by then Web Components won’t be what we know today. Just like React, it will have supporting libraries and even visual builders to allow developers to build applications easier.

Even then, don’t forget that React is also used outside of web development. It’s more likely that Web Components will one day become an alternative option for developing web applications, rather than replace the need for libraries entirely.

Conclusion

Web Components is a set of different technology being used together to help you write reusable elements that are encapsulated from the rest of your code. On the other hand, React is a JavaScript library meant to help you write user interface in a declarative way.

A scalable modern front-end development requires many other things besides components. That’s why you don’t have to be afraid to use React and its ecosystem of tools and libraries. It surely won’t be replaced by Web Components anytime soon.

Learn More

--

--

Web Developer and Writer. Sharing what I learn on productivity and success.