JSX under the hood
Published: 2024-01-25 19:04:42

# What is JSX

JSX, which stands for **JavaScript XML**, is simply a way of calling a function from the React library that would represent some DOM element like `<div>` or a custom React component in a way that is easier to understand.

# JSX Compiled

There are two answers to what your JSX compiles to depending on if you're using some version of React that was released before or after React 17. If you’re using any version of React before v17.0, then your JSX is being compiled to the function `React.createElement`. If you’re on the other side of the line then it’s being compiled to the `jsx` function. From your perspective, there should not have been much of a change in how you write your JSX, since this was a change that would mainly affect compilers like Typescript and Babel. The only exception would be that you would no longer need to have `React` in scope. You can play around with how it [here](https://babeljs.io/repl/#?browsers=defaults%2C%20not%20ie%2011%2C%20not%20ie_mob%2011&build=&builtIns=false&corejs=3.21&spec=false&loose=false&code_lz=GYVwdgxgLglg9mABACwKYBt1wBQEpEDeAUIogE6pQhlIA8AJjAG4B8AEhlogO5xnr0AhLQD0jVgG4iAXyJA&debug=false&forceAllTransforms=false&modules=false&shippedProposals=false&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=module&lineWrap=true&presets=react&prettier=false&targets=&version=7.23.8&externalPlugins=&assumptions=%7B%7D) if you’re curious.

## Before React 17

As mentioned, your JSX would call `createElement` under the hood. This function takes a maximum of 3 parameters: 

- `type`: which accepts the name of a valid react component type. This could be a tag name such as ‘div’ or ‘span’ or the name of a react component such as ‘MyCustomComponent’.
- `props`: which must either be null or an object. If you pass null it will be treated like an empty object. React will create an element with props matching the props you have passed.
- `children`: This parameter is optional. The value passed into this property is either a single invocation of the `createElement` function or an array of them.

As a quick example of what your components look like under the hood, let's look at the following component:

```jsx
import React from 'react'

export const App = () => {
	return <div>Hello World</div>
}
```

Compiling it to JavaScript gives us:

```jsx
import React from 'react'

export const App = () => {
	return React.createElement("div", {}, "Hello World")
}
```

## After React 17

The same hello world component we created above would be compiled to this instead:

```jsx
import { jsx as _jsx } from "react/jsx-runtime";
export const App = () => {
  return _jsx("div", {
    children: "Hello World"
  });
};
```

And you would no longer need `React` in scope. 

```jsx
// This would only be a valid component from React 17+
export const App = () => {
	return <div>Hello World</div>
}
```

The main motivation for this switch was to simplify how React worked under the hood and reduce the amount of concepts you would have to learn to use React. This switch also provided some performance improvements.

# Sources

1. https://www.codeguage.com/courses/react/jsx
2. https://www.telerik.com/blogs/how-jsx-react-works-under-hood
3. https://github.com/reactjs/rfcs/blob/createlement-rfc/text/0000-create-element-changes.md
4. https://legacy.reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html