React is great...but you should try Lit.
Tags: design, react, lit, javascript
Published: 2022-08-29 19:31:58

Does anyone else out there need a quick break from React? For just a few minutes maybe?

I've been using React for years now, and I miss the days where it felt new and exciting. In my brain, React has gone from a sports car to a minivan. It's still **very** good at what it does, but I'm a little bored of it. I don't get very excited using it anymore. We've lost our spark, you might say.

So, I thought I would try something new and get [Lit](https://lit.dev/) for a little while.

You heard me.

So what is [Lit](https://lit.dev/)? Per the "about" section on their [github](https://github.com/lit/lit/) page: **Lit is a simple library for building fast, lightweight web components.** 

Their slogan is:

![Simple. Fast. Web Components.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0sskjud9tnazgy9gk3u5.png)

If you don't know what a web component is, take a step backwards here and [read about web components on MDN](https://developer.mozilla.org/en-US/docs/Web/Web_Components). 

Put simply, web components are a set of native browser APIs that let you create your own HTML elements. Those elements can do whatever you want them to. **Lit is a library that wraps around web components, making them easier to work with.** Instead of setting up web components using the native APIs directly, you can use Lit to make **Lit Components**.

Your next question might be:

- That's not what React does at all...so is Lit really comparable?

- Can I use Lit to build web apps, websites, and user interfaces, just like I can with React? Is that even what Lit is meant for?

Yes, **Lit is comparable to React** in many ways. Yes, **you can use it to build websites, web apps, and UI's**. And **yes, it's intended to be used for those things**. 

It even does some things React can't do (gasp).

Let's start looking at the differences between a React component and a Lit component. I made a silly little component that takes in a string from user input, and spits it out reversed. Imports not included. And just assume `reverseString` does what it says it does, in both cases.

The **React Component**:

```javascript
export default function TextReverser() {
  const [revText, setRevText] = useState("");
  const inputElem = useRef();

  const handleClick = () => {
    setRevText(reverseString(inputElem.current.value));
  };

  return (
    <div>
      <input ref={inputElem} type="text"></input>
      <button onClick={handleClick}>Reverse Me!</button>
      {revText && <h2>{revText}</h2>}
    </div>
  );
}
```

Here's the same thing as a **Lit Component**:

```javascript
@customElement('text-reverser')
export class TextReverser extends LitElement {
  @state()
  private revText: string = '';
  
  @query('#input')
  inputElem!: HTMLInputElement;
  
  handleClick() {
   this.revText = reverseString(this.inputElem.value)
  }
  
  render() {
    return html`
     <div>
      <input id="input" type="text"></input>
      <button @click=${this.handleClick}>Reverse Me!</button>
      ${this.revText && html`<h2>${this.revText}</h2>`}
     </div>
    `;
  }
}
```
Oh boy! Such wow! So many new things to talk about and look at.

First, Lit uses [TypeScript](https://www.typescriptlang.org/). It's not required, but it's encouraged and it's awesome. It saves you time on some syntax by enabling the use of decorators. It also gives you strong typing. It also gives you code completion. 

**Why would you not want those things?**

Second, Lit components are class based. Less wow, if class syntax is not your thing. But if I had to guess, I would think that Lit will eventually get support for function based Lit components. I mean, you gotta stay with the times.

To compare what's going on...

**In React:**
- I used `useState` to manage state for the value of `revText`.
- I used `useRef` to grab a reference to the input element DOM node.
- I wrote a `handleClick` function which gets called when the button is clicked. It reverses the string and sets the new value for `revText` using `setRevText`, which causes the component to re-render.
- I rendered html by returning JSX. If `revText` has a value, it displays it in an `h2`.

**In Lit:**
- I used the `@state` decorator to initialize some internal state for the component: `revText`. I access that in other places in the component using `this.revText`.
- I used the `@query` decorator to grab a reference to the input element DOM node.
- I wrote a `handleClick` method which gets called when the button is clicked. It reverses the string, and reassigns `this.revText` to that new value. Because `this.revText` was initialized using the `@state` decorator, when its value is reassigned, the component re-renders.
- I rendered html in the `render` method of the component, by returning a [tagged template literal](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#tagged_templates), by using Lit's `html` tag function. If `this.revText` has a value, it displays it in an `h2`.

So what did we just learn?

### They both encapsulate state & behavior.
Lit and React components both generally implement the same concept: encapsulating state and behavior into little interactive UI bits.

Mmmm....little bits.

### They are both composable
Lit and React are both component-based. For each library, you can create more complex UI's by composing your components together. I didn't show how to do this in my code examples above, so here's some reading if you want to dig in further:

- [Composing Lit Components](https://lit.dev/docs/composition/overview/)
- [Composing React Components](https://reactjs.org/docs/components-and-props.html#composing-components)

### They are both reactive.
There is a [Lit component lifecycle](https://lit.dev/docs/components/lifecycle/) (no virtual DOM required) and there is a [React component lifecycle](https://reactjs.org/docs/react-component.html#the-component-lifecycle). When the component state changes, the UI reflects that change. 

SIDE NOTE: **they both can use redux**. [Check out this article](https://vaadin.com/blog/using-redux-in-a-litelement-app) to learn how to set that up for Lit.

<img width="100%" style="width:100%" src="https://media.giphy.com/media/ukCFEU6Cg5MCCDoaVN/giphy-downsized-large.gif">

Lit is starting to feel pretty similar to React, after unpacking things a little.

**So what's truly different about Lit?**

### Lit is closer to the browser
With Lit, a lot of the heavy lifting is done by native browser APIs, instead of by additional framework boilerplate code that also has to be downloaded.

I really like this, because it makes sense in my head to use things that are already freely available. You wouldn't make your own ice using ice trays if your fridge already had an ice machine, right?

Because of the emphasis towards leaning on what the browser already offers us (web components), Lit is a tiny library - about 5kb when minified and compressed. So if you're worried about page load and interested in browser features, Lit makes a good argument for itself.

### Lit is interoperable (can be used in other things)
Because a Lit component is just a web component at the end of the day, **you can use Lit anywhere!** You can use Lit on its own, or you can slide Lit components into projects that are using any other front-end framework.

This is especially exciting for the purposes of implementing a **design system**, for instance. In one of my previous jobs I helped work on one specific implementation of our companies design system - the one that was used in our CMS. Folks from other teams that used React had to create their own React based design system implementation. And so on and so forth for all the other frameworks we used, of which there were a good number. So you can imagine there was a lot of developer time spent on rebuilding the same components over and over for different frameworks.

**What if you could just implement your design system once?** And reuse it everywhere? That's something Lit can offer. If you need to use one of your design system components in React - first build it with Lit. Then, pull that Lit component into React and get going.

For further reading: 
- [Check out this article](https://www.tderflinger.com/en/litelement-react-app) on how to integrate a Lit component into a React component.
- Lit also has a separate package you can use called [@lit-labs/react](https://www.npmjs.com/package/@lit-labs/react), which provides a utility to make a React component wrapper for a Lit component.


### Parting thoughts

The main thing I want you to get from this article: **Lit is cool, and you should give it a try**! Please hear me when I say this: React is also excellent at what it does, and this article shouldn't be construed as a recommendation to never use React ever again.

Sometimes it's just nice to branch out, is all.

As a developer, learning should be a constant priority. So if you're feeling how I was feeling about React, and want to feel that spark again, I recommend learning Lit! They've got incredible [documentation](https://lit.dev/docs/) and [interactive tutorials](https://lit.dev/tutorials/), by the way.

Thanks for reading! If you want to read any of my other articles, you can find them at [quickwinswithcode.com](https://www.quickwinswithcode.com/).

{% user roberttate %}