Haunted: React Hooks for Web Components

Daniel Alarcón
Passionate People
Published in
3 min readSep 17, 2019

Hooks have been the cool boy since the beginning of this year with the release of React 16.8. Some frameworks have created their implementation like Vue-hooks, and some people have made their hook recipes.

But, what are Hooks?

Hooks propose a whole new paradigm for controlling the state of your application and for creating side-effects using just functions. It’s pretty common to create a class in React or Web Components when some lifecycle, state or logic is needed. Hooks enable us to create a web application without using classes.

Hooks and Web Components? 😱

Web Components are well known for following their own rules, for not always being up to date with the latest trends, and moreover, creating a Web Component involves creating a class

Recently I was reading two articles about how to create setInterval in a declarative way and how to simplify the use of the local storage. I was speechless, I loved how magic and declarative the code from these examples looked. I wanted to integrate them in my current project but we mainly use web components with Lit Element, so how do heck could I use them?

Haunted to the rescue!👻

Haunted is a library created by Matthew Phillips, which introduces the React’s Hooks API for standard web components and lit-html or hyperHTML.

“Haunted is all about writing plain functions that can contain their own state”, says Matthew Philips.

Learn by doing

We are going to see how does Haunted solves some common problems from an application like managing an internal state, fetching some data or reacting to some prop changes.

Managing local state — useState🐉

A typical example to illustrate how a framework or library works it’s to create a counter.

With LitElement for example, we need to create a class, a method to modify the count and to initialize the counter.

Using Haunted it’s as easy as creating a function and using useState for modifying the state.

useState returns a state property and a function to update it. So in our example, every time that setCount gets called count will get updated and it enqueues a re-render of the component.

Give me the data! — useEffect 🦇

This popular effect accepts one function that will run after every render. The second argument is an array of values that determine when the effect should run or not.

It’s widely used for fetching data. Supplying an empty array as the second argument secures the execution of the effect only once.

Using async/await for fetching data after the first render and combining it with useState, creates a simple pattern for fetching and rendering information in our web application.

VAT calculator — an advanced scenario for useEffect 🐱‍👤

The second argument from useEffect can be used for re-rendering only when a prop changes. So imagine a VAT calculator that calculates the price incl. VAT when the price excl. VAT changes. This could be achieved creating an effect that makes the calculation every time that the price excl. VAT gets set.

You can experiment with the pen to see what happens when priceExclVAT gets removed from useEffect, short answer: the component won’t re-render!

Pros and Cons

Like any library, Hooks have some benefits and disadvantages, let’s see them:

Pros

  • Hooks are easy to create, reuse and share🍭
  • No need of using classes again 🎈
  • useEffect feels better than having tons of lifecycles 🐴
  • It forces you to create declarative code 👩‍💻

Cons

  • Hard for beginners😵
  • Easy to create infinite loops in you don’t respect their rules 🐙
  • It takes time to master it, especially when creating your own hooks ⚓

Conclusion 🦉

Haunted is a breath of fresh air in the Web Components scene, this new paradigm brings to the developer a new range of possibilities. In our project we didn’t replace LitElement completely, we are introducing Haunted gradually and enjoying/learning during the path.

Big shoutout to Matthew Phillips and to their contributors for creating and maintaining such a fantastic library 🙌👻🎈

--

--