Muhi Logo Text
Work With MeAboutTestimonialsBlog

Web Components with React Hooks

Last updated on May 29, 2021

react
web components
React Web Component

Web Components are of great use when it comes to creating a future proof component-based design system that can be interoperable and shared across multiple products.

Unfortunately, React is one of the few modern libraries that does not have full support to Web Components, especially when it comes to handling events. The reason is that React implements its own synthetic event system, it cannot listen for DOM events coming from Web Components.

The great news is that you don’t need to rewrite all your design system from scratch using React. There is a simple workaround that requires creating thin wrappers and subscribing to DOM events.

In this example, I’m using Wired Elements to make an input Web Component work with React. Wired Elements are a set of common UI elements with a hand-drawn, sketchy look. The library uses LitElement for creating Web Components.

Also, in this article, I’m solving specifically the problem with capturing DOM events through a React component wrapper. Please refer to custom-elements-everywhere.com if you want to look at all open issues regarding React and Web Components support.

Create React App

Create a new React App.

npx create-react-app react-webcomponent

Install Wired Elements

Full documentation on Wired Elements is available on their main repository

npm i wired-elements

Import Wired Input Element

In this section, we will add a Wired Input Element without a wrapper and show how the onChange event will not be triggered as React does not detect DOM events.

import './App.css';
import 'wired-elements';

function App() {
  function handleInput(e) {
    console.log(e.target.value);
  }
  return (
    <div className="App">
      <wired-input onChange={handleInput}></wired-input>
    </div>
  );
}

export default App;

Quick summary of the code above:

  • Reused App.js file and cleaned up unused code
  • Imported wired-elements
  • Added <wired-input> to the template
  • Created a handle input function to print the value being typed when onChange is triggered

Now as expected, when typing, the console doesn’t print anything:

Create a component wrapper

Let’s add a new react component and call it WiredInput.js. It will subscribe to the input event and call onChange function from the component props

import { createRef, useEffect } from "react";
import "wired-elements";

function WiredInput({ onChange }) {
  const inputRef = createRef();
  useEffect(() => {
    inputRef.current.addEventListener("input", (e) => {
      if (onChange) {
        onChange(e);
      }
    });
  }, [inputRef, onChange]);
  return <wired-input ref={inputRef}></wired-input>;
}

export default WiredInput;

Here are some details of what we did in the code above:

  • In line 5, created a reference to the element using createRef and named it inputRef
  • In line 6, added a useEffect function to be triggered when the DOM is ready (this way we ensure inputRef is not empty)
  • Line 7, subscribe to the input event
  • Line 8, checking if onChange is not undefined then call the function and pass it the event
  • Line 13, added the wired input element with inputRef

Test input change event

Now that we have the wrapper component ready, let’s put it into action!

First, let’s update app.js to use the new component:

import './App.css';
import WiredInput from './WiredInput';

function App() {
  function handleInput(e) {
    console.log(e.target.value);
  }
  return (
    <div className="App">
      <WiredInput onChange={handleInput}></WiredInput>
    </div>
  );
}

export default App;

Here is a demonstration of our final working code:

You can access the complete repository here.

Bye for now 👋

If you enjoyed this post, I regularly share similar content on Twitter. Follow me @muhimasri to stay up to date, or feel free to message me on Twitter if you have any questions or comments. I'm always open to discussing the topics I write about!

Recommended Reading

Learn how to create dynamic, customizable inputs that enhance user experience with React Material UI FormControl.

react
mui

Discussion

Upskill Your Frontend Development Techniques 🌟

Subscribe to stay up-to-date and receive quality front-end development tutorials straight to your inbox!

No spam, sales, or ads. Unsubscribe anytime you wish.

© 2024, Muhi Masri