Wondering what’s next for npm?Check out our public roadmap! »

    TypeScript icon, indicating that this package has built-in type declarations

    0.2.0 • Public • Published


    This package aims to give you the opportunity to use the JSX syntax introduced by React, without using React at all.

    Key differrences with React API:

    • No VirtualDOM (less overhead, but also less reactivity)
    • Everything is asynchronous
    • No Component life-cycle


    Get Started

    import { h } from "@aduh95/async-jsx";
    const element = <div>Hello World</div>;
    console.log(element instanceof Promise); // true
    element.then(domElement => console.log(domElement instanceof HTMLElement)); // true

    It is recommanded to add this CSS to your page to avoid custom elements leaking into your design:

    conditional-element {
      display: contents;
    dom-portal {
      display: none;

    Build tools

    With Babel

    You can use the @babel/plugin-transform-react-jsx package:

      "plugins": [
          { "pragma": "h", "pragmaFrag": "Fragment" }

    With TypeScript

    In the tsconfig.json:

      "compilerOptions": {
        "jsx": "react",
        "jsxFactory": "h"

    With dynamic imports

    You can define a component in a separate file and lazy-load it:

    /* Greetings.js */
    import { h } from "@aduh95/async-jsx";
    // You can use an arrow function instead of a class
    export default props => (
      <div className={props.className}>Hello {props.name}</div>
    /* App.js */
    import {
    } from "@aduh95/async-jsx";
    const Greetings = lazy(() => import("./Greetings.js"));
    export default class App extends Component {
      stateObservers = new Set();
      greetingName = "";
      _handleNewName = this.handleNewName.bind(this);
      handleNewName(ev) {
        const { target } = ev;
        this.greetingName = target.value;
        this.stateObservers.forEach(fn => fn("ready"));
      render() {
        return (
                ready: <Greetings name={this.greetingName} />,
                askForName: (
                    placeholder="What's your name"


    I have added a React-compatible StatefulComponent, which can be used the same way as a React.Component. However, because of the lack of VirtualDOM, it can be highly inneficient to use it. For example, let's take the Clocl example from React docs:

    import { h, StatefulComponent } from "@aduh95/async-jsx";
    class Clock extends StatefulComponent {
      constructor(props) {
        this.state = { date: new Date() };
      componentDidMount() {
        this.timerID = setInterval(() => this.tick(), 1000);
      componentWillUnmount() {
      tick() {
          date: new Date(),
      render() {
        return (
            <h1>Hello, world!</h1>
            <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      .append(renderAsync(<Clock />, null, console.error));

    This will work apparently, but at each tick, 3 DOM elements are initiated. Perf difference may not be visible on that small example, but you can imagine that having a whole site re-render everytime something change will put a lot of pressure on small-CPU clients.

    SVG Elements

    Because SVG Elements cannot be created using Document.prototype.createElement, but by Document.prototype.createElementNS, they cannot be created by the usual h p(or createElement) function. pIf you want to create SVG elements using JSX, you can put them in a separate module:

    // Logo.js
    import { createSVGElement as h } from "../utils/jsx.js";
    export default () => (
        <path />

    Then you can import this module in another component:

    import { Component, h } from "../utils/jsx.js";
    import Logo from "./Logo.js";
    export default class Header extends Component {
      render() {
        return (
            <Logo />


    This repo is using TypeScript, you can use it to have access to the documentation during development. The API is defined by the .d.ts files.


    npm i @aduh95/async-jsx

    DownloadsWeekly Downloads






    Unpacked Size

    63.8 kB

    Total Files


    Last publish


    • avatar