# How to use Web Components with Next.js and TypeScript

Original: https://swyx.io/how-to-use-web-components-with-next-js-and-typescript-4gg1
Published: 2020-04-03

> In my livestream today I had the need to bring in a spinner component to show work in progress in my app. However found that existing React spinners were too heavy. That's when I…

In [my livestream today](https://dev.to/swyx/make-your-own-dev-to-cms-livestream-part-4-6em) I had the need to bring in a spinner component to show work in progress in my app. However found that existing React spinners were too heavy. That's when I had the idea to use web components in my Next.js (React/Preact) app for the first time ever!

We'll use https://github.com/craigjennings11/wc-spinners/ as a case study.

## Web Components 101

Normally to use a webcomponent in a project you just import it like a library:

```js
  import 'wc-spinners/dist/atom-spinner.js';
```

and then use it in our JSX/HTML:

```html
<div> 
    <atom-spinner/> Loading
</div>
```

The web component will encapsulate behavior and styles without the weight of a framework, which is very nice for us.

However when it comes to Next.js and TypeScript, we run into some problems.

## TypeScript and Web Components

When you use TypeScript with JSX, it tries to check every element you use to guard against typos. This is a problem when you've just registered a component that of course doesn't exist in the normal DOM:

```
Property 'atom-spinner' does not exist on type 'JSX.IntrinsicElements'.ts(2339)
```

The solution I got from [this guy](https://wespeter.com/posts/consuming-web-component-react-typescript/) is to use [declaration merging](https://www.typescriptlang.org/docs/handbook/declaration-merging.html) to extend TypeScript:

```ts
// declarations.d.ts - place it anywhere, this is an ambient module
declare namespace JSX {
  interface IntrinsicElements {
    "atom-spinner": any;
  }
}
```

## Next.js and Web Components

The next issue you run into is server side rendering.

```
ReferenceError: HTMLElement is not defined
```

WC's famously don't have a great SSR story. If you need to SSR WC's, it seems the common recommendation is to use a framework like Stencil.js. I have no experience with that.

Since in my usecase I only needed the WC clientside, I found that I could simply defer loading the WC:

```js
function Component() {
  React.useEffect(() => import("wc-spinners/dist/atom-spinner.js")
  , [])
  return (<div>
        // etc
        <atom-spinner />
        </div>)
}
```

And that's that! Enjoy using the platform!
