Alex Merced I am a developer, educator, and founder of devNursery.com.

Create reusable components with Mitosis and Builder.io

4 min read 1339

Reusable Components Mitosis

A common challenge among development teams is using the same language; while one subteam is using Vue, another may be using React, causing redundant work and forcing you to create shared components twice.

In this tutorial, we’ll explore Mitosis, a tool that can compile code to standard JavaScript in addition to frameworks and libraries like Angular, React, and Vue, allowing you to create reusable components.

We’ll review some background information to clarify when you should use Mitosis, then install Mitosis in a new project to see it in action. Let’s get started!

Mitosis vs. web components

While some developers initially turned to web components to create reusable components, they encountered issues like web components’ browser compatibility and its lower-level approach, which made the creation of reusable components an intensive process.

Similarly, certain libraries like React had workflows that made incorporating web components difficult, leading to the creation of solutions like Google’s LitElement, Ionic, and Stencil.js.

Meanwhile, a parallel trend arose in Svelte and SolidJS. Intended for building applications, Svelte and SolidJS made huge performance gains by compiling the source code to standard JavaScript, creating bundles that were smaller and faster than web components.

Mitosis builds on the functionality of Svelte and SolidJS, employing the same compilation speed and allowing you to recompile a component into different frameworks and libraries from the same codebase. The compiled component operates like any other component in the framework.

Similar to SolidJS, Mitosis uses a version of JSX that compiles the components to JSON. Plugins then compile the components to different targets, allowing you to create tooling in two directions:

  • Code that can be converted into Mitosis JSON
  • Plugins that compile or serialize JSON to target frameworks

For these reasons, Mitosis supports no-code tools. For example, Builder.io allows you to create your website using a visual tool, then compile it to the framework of your choice. Builder.io acts as a CMS but is powered by Mitosis.

Mitosis uses WYSIWYG editing and a SPA framework for compilation. Now that we understand how Mitosis works, let’s create a component with Mitosis.

We made a custom demo for .
No really. Click here to check it out.

Getting started with Mitosis

First, we’ll install the Mitosis CLI:

npm install -g @builder.io/mitosis-cli

Create an empty folder on your computer. In your terminal, open the folder and create a new npm project:

npm init -y

Next, we’ll install Mitosis:

npm install @builder.io/mitosis

Create a file called component.lite.jsx. lite.jsx is the extension for Mitosis projects. Next, we’ll install the Builder.io VS Code extension, which provides syntax highlighting for lite.jsx files.

In the component.lite.jsx file, add the following code:

import { useState, Show, For } from "@builder.io/mitosis";
export default function Component(props){
const state = useState({count: 0})

In the code above, we declare state using the useState Hook. Now, when any property in the state object is changed, the UI will render.

Next, add the following code block to component.lite.jsx, which will return JSX like React or SolidJS:

    return (<div>
        {/* DISPLAY SOME JSX CONDITIONALLY */}
        <Show when={state.count > 10}>
            <h1>You Win!!!</h1>    
        </Show>

        {/* DISPLAY THE COUNT */}
        <h1>{state.count}</h1>

        {/* BUTTON TO ADD TO THE COUNT */}
        <button onClick={(event) => {state.count += 1}}>Click to Add One</button>
    </div>)
}

In the code above, the show component allows us to conditionally render the UI. Because state is updated with plain reassignments, there is no need to add the setState function, which we’d use in React. Lastly, notice that all our state can be bundled into one object.

Now that our component is built, let’s see some examples of our component compiled to different frameworks!

Compilation in Mitosis

React

Let’s use Mitosis to compile our component into a React component:

mitosis compile --to=react component.lite.jsx > component.jsx

The --to= flag lets us select the framework that we’ll compile our Mitosis component to. When compiled to React, we’ll get the following output:

import { useContext } from "react";
import { useLocalObservable } from "mobx-react-lite";
export default function Component(props) {
  const state = useLocalObservable(() => ({ count: 0 }));
  return (
    <div>
      {state.count > 10 && (
        <>
          <h1>You Win!!!</h1>
        </>
      )}
      <h1>{state.count}</h1>
      <button
        onClick={(event) => {
          state.count += 1;
        }}
      >
        Click to Add One
      </button>
    </div>
  );
}

Vue

--to=vue component.lite.jsx > component.vue

When compiled to Vue, our component will look like the code below:

<template>
  <div>
    {{/* DISPLAY SOME JSX CONDITIONALLY */}}
    <template v-if="count > 10">
      <h1>You Win!!!</h1>
    </template>

    {{/* DISPLAY THE COUNT */}}
    <h1>{{ count }}</h1>

    {{/* BUTTON TO ADD TO THE COUNT */}}
    <button @click="count += 1">Click to Add One</button>
  </div>
</template>
<script>
export default {
  name: "Component",

  data: () => ({ count: 0 }),
};
</script>

Svelte

--to=svelte component.lite.jsx > component.svelte

When we compile our Mitosis component to Svelte, we’ll get the following output:

<script>

     let  count= 0

</script>

<div >

  {#if count > 10 }       
    <h1 >You Win!!!</h1>
  {/if}

  <h1 >{count}</h1>

  <button  on:click="{event => 
    count += 1;
  }" >Click to Add One</button>

</div>

Angular

--to=angular component.lite.jsx > component.tsx

When we compile our Mitosis component to Angular, it will look like the code below:

import { Component } from "@angular/core";

@Component({
  selector: "component",
  template: 
    <div>
      <ng-container *ngIf="count > 10">
        <h1>You Win!!!</h1>
      </ng-container>

      <h1>{{count}}</h1>

      <button
        (click)="
      count += 1;
    "
      >
        Click to Add One
      </button>
    </div>
  ,
})
export default class Component {
  count = 0;
}

web components

--to=customElement component.lite.jsx > component.js

When compiled to web components, we’ll get the following output:

/**
 * Usage:
 *
 *  <component></component>
 *
 */
class Component extends HTMLElement {
  constructor() {
    super();

    const self = this;
    this.state = { count: 0 };

    // Event handler for 'click' event on button-1
    this.onButton1Click = (event) => {
      this.state.count += 1;
      this.update();
    };
  }

  connectedCallback() {
    this.innerHTML = `
      <div>
        <span data-name="show">
          <h1>You Win!!!</h1>
        </span>

        <h1>
         <span data-name="div-1"><!-- state.count --></span>
        </h1>

        <button data-name="button-1">Click to Add One</button>
      </div>
     <style></style>`;
    this.update();
  }

  update() {
    this.querySelectorAll("[data-name='show']").forEach((el) => {
      el.style.display = this.state.count > 10 ? "inline" : "none";
    });

    this.querySelectorAll("[data-name='div-1']").forEach((el) => {
      el.innerText = this.state.count;
    });

    this.querySelectorAll("[data-name='button-1']").forEach((el) => {
      el.removeEventListener("click", this.onButton1Click);
      el.addEventListener("click", this.onButton1Click);
    });
  }
}

customElements.define("component", Component);

As you can see, it is straightforward to install Mitosis, create a component, and then compile it to the language, library, or framework of your choice. We covered several examples in this tutorial, but only scratched the surface; other compilation targets include Swift, Liquid.js, SolidJS, React Native, and more.

Conclusion

When it is impossible to use the same language as the rest of your team, Mitosis is a helpful tool that saves time by reducing redundant work. 

Mitosis allows you to write one codebase for an individual component then compile it to one of many targets. It facilitates low-code and no-code solutions for creating fast, reactive applications.

We explored the Builder.io plugin, but another popular plugin is the figma-html plugin, which allows you to turn your Figma design into code for any framework.

As you build your own reusable components, you can see the visual results using the JSX-lite fiddle from Builder.io. However, at the time of writing, this feature is still in an early preview stage. I hope you enjoyed this tutorial!

: Full visibility into your web apps

LogRocket is a frontend application monitoring solution that lets you replay problems as if they happened in your own browser. Instead of guessing why errors happen, or asking users for screenshots and log dumps, LogRocket lets you replay the session to quickly understand what went wrong. It works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store.

In addition to logging Redux actions and state, LogRocket records console logs, JavaScript errors, stacktraces, network requests/responses with headers + bodies, browser metadata, and custom logs. It also instruments the DOM to record the HTML and CSS on the page, recreating pixel-perfect videos of even the most complex single-page apps.

.
Alex Merced I am a developer, educator, and founder of devNursery.com.

Testing accessibility with Storybook

One big challenge when building a component library is prioritizing accessibility. Accessibility is usually seen as one of those “nice-to-have” features, and unfortunately, we’re...
Laura Carballo
4 min read

One Reply to “Create reusable components with Mitosis and Builder.io”

  1. I’ll check this out, thanks. 👍

    In Svelte you can compile components to regular web components, and use regular web components with ease in Svelte projects or other frameworks. We’ve had tremendous ease and great success with that approach. I’ll evaluate this to see how it compares. Thanks for the heads up and writeup. Cheers.

Leave a Reply