DEV Community

Cover image for How to use custom JSX in Deno?
WJH
WJH

Posted on

How to use custom JSX in Deno?

This article is meant for Deno authors who wanted to create a frontend library in Deno that utilises JSX without using React.

Before you start, please make sure you're using Deno v1.1.0.

deno upgrade --version=1.1.0

Basically, to create your own JSX types in Deno, you just need to complete the following steps:

1) Think of a name for your framework. For demonstration, I'll use the name Spongebob.

2) Create a tsconfig.json file with the default Deno tsconfig.

3) Update the value of "jsxFactory" in the tsconfig.json to "Spongebob.createElement".

4) Create a file named jsx.ts with the following content:

export namespace Spongebob {
  export const createElement = (tag: string | Function, props: object, ...children: any[]) => {
    if(typeof tag === 'function') {
      return tag({...props, children})
    }
    else {
      return [tag, props, children]
    }
  }
}
declare global {
  namespace JSX {
    interface IntrinsicElements {
      div: {
        id?: string
        style?: { }
      }
    }
  }
}

5) To try out the JSX types, create a file named client.tsx.

import { Spongebob } from "./jsx.ts";

const EntryComponent = () => {
  return (
    <div id="patrick">
      <MySubComponent drugs={["rick", "morty"]} />
    </div>
  );
};

const MySubComponent = (props: { drugs: string[] }) => {
  return (
    <div>
      {props.drugs.map((drug) => <div>{drug}</div>)}
    </div>
  );
};

console.log(JSON.stringify(<EntryComponent />, null, 2));

6) Run this command to test out.

deno run --config tsconfig.json client.tsx

By the way, if you are lazy but you want to try out, you can refer to this repository.
Thank you for reading!

Discussion (1)

Collapse
michaelcurrin profile image
Michael • Edited

Deno lint gives a warning:

declare global {
  namespace JSX {
    // ...
  }
}
Enter fullscreen mode Exit fullscreen mode
custom typescript modules are outdated
Enter fullscreen mode Exit fullscreen mode

But this works great:

declare namespace JSX {
  interface IntrinsicElements {
    // deno-lint-ignore no-explicit-any
    [elemName: string]: any;
  }
}
Enter fullscreen mode Exit fullscreen mode

It comes from TS docs - IntrinsicElements.

I've applied this here in my newly-released Deno React app:

src/shims-react.ts

MichaelCurrin - react-deno-quickstart