JSX Alternatives

Apurva Jain
Geek Culture
Published in
6 min readJun 8, 2021

--

JSX is a very popular choice nowadays for templating in various frameworks, not just in React. However, what if you don’t like it, or have a project where you want to avoid* using it, or just curious how you can write your React code without it? The simplest answer is — Yes, there are various alternatives to JSX. Let's explore them one by one in this article.

*Disclaimer: Personally, I like JSX and use it in all my projects with React. However, I researched this topic for a bit and would like to share my findings.

JSX — What & How?

Before we jump into the alternatives let's understand what is JSX and how does it work?

With the introduction of React, the term JSX has become quite popular. JSX stands for JavaScript XML used in React to easily write HTML and JavaScript together.

You would be surprised to know that JSX is NOT a requirement for using React. As per the official documentation of React,

Fundamentally, JSX element is just syntactic sugar for calling React.createElement(component, props, ...children).

In the below example, we’re returning the JSX from the MyDemo component and rendering that on the screen using the ReactDOM.render method.

class MyDemo extends React.Component {
render() {
return (
<div className={"alpha"} onclick={some}>
{"abc"}
<div>xyz</div>
</div>
);
}
}

This is simple JSX code in React. But the browser does not understand this JSX because it’s not valid JavaScript code.

So to convert it to browser understandable JavaScript code, we use a tool like Babel which is a JavaScript compiler/transpiler.

When the Babel executes the above JSX, it converts it to the following code:

class MyDemo extends React.Component {
render() {
return React.createElement("div", {
className: "alpha",
onclick: some
}, "abc", React.createElement("div", null, "xyz"));
}
}

Every JSX is converted to the React.createElement function call that the browser understands.

Knowing how to convert JSX to React.createElement is very important as a React developer (it's also a popular interview question).

JSX Alternatives

Lets explore JSX alternatives from the point of making code more readable and avoid compilation complexity in your build environment:

1. React.createElement function

The React.createElement has the following syntax:

React.createElement(type, [props], [...children])

Let’s look at the parameters of the createElement function.

  • type can be an HTML tag like h1, div or it can be a React component
  • props are the attributes you want the element to have
  • children contain other HTML tags or can be a component

The React.createElement call will also be converted to the object representation like this:

You can see this object representation if you assign the JSX to some local variable and log it in the console. So, anything you can do with JSX can also be done with just plain JavaScript.

Tip: If you want to see the JSX to React.createElement conversion code, you can navigate to this application where you can write your JSX code on left and see the converted code on the right.

2. Renaming React.createElement function

While the resulting code is perfectly valid, and we can write all our React code in this style, there are several problems with this approach.

The first problem is that it is extremely verbose. Like really verbose, and the main offender here is React.createElement.

So the first solution is just to save it into a variable, usually named h after hyperscript. This will already save you a lot of text, and make it more readable. To illustrate that, let’s rewrite our past example:

const h = React.createElement;class MyDemo extends React.Component {
render() {
return h("div", {
className: "alpha",
onclick: some
}, "abc", React.createElement("div", null, "xyz"));
}
}

3. Hyperscript

If you play a bit with either React.createElement or h, you can see that it has several flaws. To start with, this function requires 3 arguments, so in case there are no properties, you have to provide null, or className, probably the most common property, requires writing a new object every time.

As an alternative, you can use the react-hyperscript library. It does not require providing empty props, and also allows you to specify classes and ids in an emmet-like style:

div#main.content -> <div id="main" class="content">

So, our code will become slightly better:

const h = require('react-hyperscript');class MyDemo extends React.Component {
render() {
return h("div.alpha", { onclick: some }, [
"abc",
h("div", "xzy")
]);
}
}

4. HTM

If you are not against JSX per se but don’t want to set up compilation in your build environment — Use htm — JSX-like syntax in plain JavaScript — no transpiler necessary. It aims to do the same (and look the same) as JSX but using template literals. This definitely adds some overhead (you have to parse these templates in the runtime), but it might worth it in your case.

It works by wrapping element function, which is React.createElement in our case, but it can be any other library with similar API, and returns a function which will parse our template and return exactly the same code as babel did, but only in the runtime.

const html = htm.bind(React.createElement);class MyDemo extends React.Component {
render() {
return html`
<div className=${"alpha"} onclick=${some}>
${"something"}
<div>something</div>
</div>
`
}
}

As you can see, it is almost the same as real JSX, we just need to insert variables in a slightly different manner; however, these are mostly details, and if you want to show how to use React without any tool setup, this might be handy.

5. Lisp-like Syntax

The idea of this one is similar to hyperscript, however, it is an elegant approach worth looking at. There are many other similar helper libraries, so the choice is purely subjective; it might give inspiration for your own projects.

The library ijk brings the idea of writing your templates using only arrays, using positions as arguments. It’s a tiny recursive factory function that allows you to write terse, declarative representations of virtual DOM trees. It does not try to mimic HTML or JSON syntax but instead a series of nested arrays to represent user interfaces.

The main advantage is that you don’t need to write h constantly (yes, even that can be repetitive!). Here is an example of how to use it:

function render(structure) {
return h('nodeName', 'attributes', 'children')(structure)
}
class MyDemo extends React.Component {
render() {
return render([
'div', { className: 'alpha', onClick: some}, [
'abc',
['div', 'xyz']
]]);
}
}

The above call to h returns a virtual DOM tree with named attributes that respect the provided schema.

JSX Gotchas

  • JSX allows us to easily write HTML elements in JavaScript and place them in the DOM without any createElement() and/or appendChild() methods.
  • To add a class in JSX, we need to use className instead of class — is a reserved keyword in JavaScript.
  • In React, all the attribute names are written in camelCase, eg. className, onChange, htmlFor, etc.
  • The HTML code must be wrapped in ONE top-level element.
const body = (
<div>
<h1>I am a Header</h1>
<h1>I am a Footer</h1>
</div>
);

JSX will throw an error if the HTML is not correct, or if the HTML misses a parent element.

Use React.Fragment to group a list of children without adding extra nodes to the DOM.

  • To write HTML on multiple lines, put the HTML inside parentheses:
const body = (
<ul>
<li>Apples</li>
<li>Bananas</li>
<li>Cherries</li>
</ul>
);
  • To add expressions to your JSX, put the expressions within curly braces { } :
const header = <h1>React is {5 + 5} times better with JSX</h1>;

The expression can be a React variable, or property, or any other valid JavaScript expression. JSX will execute the expression and return the result.

Values like undefined, null, and boolean are not displayed on the UI when used inside JSX.

  • To add a comment to your JSX, wrap it inside the /* and */ comment symbols like this:
{/* <p>This is some text</p> */}

Instead of manually typing the comment, you can use Cmd + / (Mac) or Ctrl + / shortcut keys to add or remove the comment.

  • JSX follows XML rules, and therefore HTML elements must be properly closed.
const inputForm = <input type="text" />;
const headerSection = <div>React is AWESOME</div>;

Conclusion

So, anything you can do with JSX can also be done with just plain JavaScript. Using React without JSX is especially convenient when you don’t want to set up compilation in your build environment.

This article does not say that you should not use JSX, or whether it is a bad idea. The goal of this article was to merely answer — how can you write your code without JSX, and how your code can possibly look like— curiosity is the mother of learning 😎

References:

Indtroducting JSX, JSX in depth, React without JSX, JSX Alternatives, React like JSX libraries

Thanks for reading and don’t forget to share, comment and give as many 👏 as possible 😎

--

--

Apurva Jain
Geek Culture

Full stack developer with expertise in JavaScript and React. On my radar: #travel #technology #sports #health