JSX is a syntax introduced with the React library to easier write declarative view components inside JavaScript. For many, it looks like a templating language, but there is a subtle but important difference: With JSX you move markup into JavaScript, but with templating, you move JavaScript into a markup language. It sounds like a trivial difference, but it has major practical implications. For instance, with JSX you have all of JavaScript at your disposal, which also means it can be less syntax to learn.

While JSX was introduced by React, it is built on previous work in the language standard specification called E4X (ECMAScript for XML). The standard was later deprecated and is no longer supported. React isn’t the only library using JSX. Many others support it as well, such as Vue, preact, inferno, and more.

JSX isn’t strictly necessary to make declarative views, and in many cases, I would say using JavaScript and functions are just as good or even better, but there are some advantages to JSX. In my mind the three most prominent arguments are

Interchangeability with HTML, meaning we can more easily convert back and forth. Easier communication with designers who write HTML. Making the syntax more distinct, making it easier to visually separate data transformation and UI output.

These advantages are handy even if you don’t use large frameworks or libraries. We can write a small UI library that can utilize JSX to be more declarative, but still with a very minimal footprint. This will build on many of the same concepts as a previous blog post where we create our own library, but it uses a different approach and isn’t required reading to understand this post.

Another duck enjoying the beach life reflecting on the tradeoffs of JSX.

In practicality, this implementation will require a build step to transform our code, but we will only transform the JSX through Babel and use modern language features supported by all major modern browsers.

How does JSX work?

Personally, it took some time to get used to the idea of JSX, but one of the things that made it easier for me to accept it back then was that the conceptual distance between JSX and JavaScript is small. Also, the actual syntax isn’t that different. We could almost do a Levenshtein distance comparison and talk of single-digit numbers. Let us see how it works.

If we have a package.json with the following Babel dependencies and configuration:

We can from our root (where the package.json is located), build our index.js file and get the output in clean JavaScript:

npm run build

With this setup, we can investigate what the output of JSX is. Given our index.js :

It will output:

Interesting! We see the tag is passed as a string to a function defined on the React namespace, and the last argument is the child, which is, in this case, a string of Hello, World! . If we add some attributes (or props as it is often called with React), we can see what the second argument is:

The second argument is an object passed as properties to the createElement function. How about child elements?

createElement is a variadic function where all but the first two parameters are children. We can say that the signature looks like this:

We can create a function that matches this signature and output our custom code. But for that to be possible, we somehow need to have the output of the JSX compilation be something other than React.createElement . Great news! The Babel JSX plugin supports that.

We can use Babel plugin configuration to override the function:

Now our output would be:

Perfect! All we need to do now is create our own library.