Open In App

How React JSX gets Transformed into JavaScript behind the Scenes

Last Updated : 15 Apr, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report

React has revolutionized UI development by introducing JSX, a syntax that blends JavaScript with HTML-like elements. While JSX simplifies the process of building components, understanding its inner workings is key to creating scalable and performant applications. This article explores how inline JavaScript within JSX is executed, the transformation process from JSX to JavaScript, and the tools used in this conversion, offering insights into the mechanics behind React's modern UI development approach.

How-React-JSX-Gets-Transformed-Into-JavaScript-Behind-the-Scenes
How React JSX Gets Transformed Into JavaScript Behind the Scenes?

These are the following topics that we are going to discuss:

What is JSX?

JavaScript XML or JSX is known to be an add-up in the grammar of markup languages that contain JavaScript. In many instances, JS cannot perform certain operations such as designing a website’s layout. This is why this very helpful technology is derived it enables a lot of these things to be done in JavaScript code and JavaScript code alone without the bulk of unnecessary voices.

Example:

const Greeting = () => {
return <h1>Hello, World!</h1>;
};

Under the hood, browsers don't understand JSX. Therefore, JSX must be transformed into standard JavaScript before it can be executed. This transformation process is compulsory for the seamless integration of JSX within React applications.

Why JSX?

Before directly going into the transformation process, it's essential to understand the rationale behind JSX's creation and its benefits.

  • Declarative Syntax: In contrast to writing imperatively, using JSX enables the developer to create the components declaratively, just as the UI appears in an ideal world. This approach improves the code's readability hence maintenance.
  • Enhanced Developer Experience: JSX enables the developer to structure the UI as a part of the component code, thus helping them to avoid the need to context switch to HTML.
  • Integration with JavaScript: The primary limitation of the use of JavaScript is that the variables, functions, and conditions are integrated into the markup language where it is permitted and appropriate.

Example: Conditional Rendering in JSX

const UserGreeting = ({ isLoggedIn }) => {
return (
<div>
{isLoggedIn ? <h1>Welcome back!</h1> : <h1>Please sign up.</h1>}
</div>
);
};
  • Tooling and Ecosystem Support: JSX is further enriched by an extensive array of supportive tools and libraries that make development a pleasant experience with the use of syntax highlighting, linting, and formatting.

The Role of Babel in JSX Transformation

Babel is a JavaScript compiler widely used in the React ecosystem to transform JSX into standard JavaScript. It serves as the important ladder of the JSX transformation process, enabling developers to write modern JavaScript and JSX without worrying about browser compatibility.

What is Babel?

Babel is a very famous transpiler that basically allows us to use future JavaScript in today’s browsers. In simple words, it can convert the latest version of JavaScript code into the one that the browser understands. Transpiler is a tool that is used to convert source code into another source code that is of the same level. The latest standard version that JavaScript follows is ES2020 which is not fully supported by all browsers hence we make use of a tool such as ‘babel’ so that we can convert it into the code that today’s browser understands.

Babel's Responsibilities in JSX Transformation:

  • Parsing: Babel parses the JSX code to understand its structure.
  • Transformation: It converts JSX syntax into equivalent JavaScript function calls (React.createElement).
  • Code Generation: Babel generates the transformed JavaScript code that browsers can execute.

Babel Plugins for React:

Babel utilizes plugins to handle specific transformations. For JSX, the primary plugin is @babel/plugin-transform-react-jsx, which is responsible for converting JSX syntax into React.createElement calls.

Configuration Example:

{
"presets": ["@babel/preset-env", "@babel/preset-react"],
"plugins": ["@babel/plugin-transform-react-jsx"]
}

Step-by-Step Transformation Process

Understanding the step-by-step process of how JSX is transformed into JavaScript provides valuable insights into React's inner workings. Let's explore each stage in detail.

Step 1: Parsing the JSX

This is the first step in parsing, it is where Babel scans through the JSX code in a bid to understand it is structured and what it actually means.

  • Lexical Analysis: Babel performs Constants collection as the first step in the code: breaking instructions into keywords, identifiers, operators, or others.
  • Syntactic Analysis: It takes a grammatical approach and structure to check if the language used in the code conforms to the standards set by JavaScript and JSX.

Example: Given the following JSX code

const element = <h1 className="greeting">Hello, World!</h1>;

Babel identifies:

  • const element as a variable declaration.
  • <h1 className="greeting">Hello, World!</h1> as a JSX element.

Step 2: AST Generation

After parsing and understanding a particular piece of code, Babel creates an AST, which is a structure that defines the relationship between different parts of the code in tree structures.

  • Nodes: Things like variables, functions, jsx tags and the like all become nodes within the AST.
  • Hierarchy: The AST depicts clear inter-level associations between the aspects of code.

Visualization:

Variable-Declaration-Flowchart

Step 3: Code Transformation

With the AST in place, Babel transforms the JSX elements into standard JavaScript function calls.

Transformation Process:

  • Identify JSX Elements: Babel locates nodes representing JSX elements.
  • Convert to React.createElement: Each JSX element is transformed into a React.createElement call.

Example Transformation: Original JSX

const element = <h1 className="greeting">Hello, World!</h1>;

Transformed JavaScript:

const element = React.createElement(
'h1',
{ className: 'greeting' },
'Hello, World!'
);

Explanation:

  • 'h1': The type of the HTML element.
  • { className: 'greeting' }: The props object containing attributes.
  • 'Hello, World!': The child element or text.

Step 4: Code Generation

The final stage involves generating executable JavaScript code from the transformed AST.

  • Code Emission: Babel walks through the transformed AST to produce the corresponding JavaScript code.
  • Optimization: Babel may perform additional optimizations, such as minification or dead code elimination, depending on the configuration.

Final Output:

const element = React.createElement(
'h1',
{ className: 'greeting' },
'Hello, World!'
);

Understanding the Transpiled Code

The transformed code, though functionally equivalent to the original JSX, operates differently under the hood. Let's do in detail to the React.createElement function to understand how it works.

React.createElement

React.createElement is a fundamental function in React that creates a React element, which is a lightweight description of what should appear on the screen.

Syntax:

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

Parameters:

  • type: A string representing the HTML tag (e.g., 'div', 'h1') or a React component.
  • props: An object containing attributes and event handlers (e.g., { className: 'greeting' }).
  • children: Child elements or text nodes.

Example:

const element = React.createElement(
'button',
{ onClick: handleClick },
'Click Me'
);

Equivalent JSX:

const element = <button onClick={handleClick}>Click Me</button>;

Advantages of React.createElement

  • Flexibility: It allows dynamic creation of elements based on conditions or loops.
  • Performance: React optimizes rendering by comparing elements created via React.createElement.
  • Composition: Facilitates the composition of complex UIs through nested elements and components.

Optimizations and Enhancements

While Babel efficiently transforms JSX into JavaScript, several optimizations enhance performance and maintainability.

JSX Pragma and Automatic Runtime

In earlier versions of React, developers needed to import React to use JSX because React.createElement was called explicitly. However, with the introduction of the automatic JSX runtime in React 17, Babel can automatically handle JSX transformations without the need to import React explicitly.

Benefits:

  • Cleaner Code: Reduces the boilerplate of importing React in every file.
  • Improved Tree Shaking: Helps in eliminating unused code during the bundling process.

Configuration Example:

{
"presets": [
["@babel/preset-react", {
"runtime": "automatic"
}]
]
}

React.memo and Pure Components

Optimizing component re-renders is crucial for performance. Using React.memo or Pure Components ensures that components only re-render when necessary.

Example with React.memo:

const Greeting = React.memo(({ name }) => {
return <h1>Hello, {name}!</h1>;
});

Benefit:

  • Performance: Prevents unnecessary re-renders, enhancing application performance.

Code Splitting and Lazy Loading

Dividing the application into smaller chunks and loading them on demand reduces initial load times.

Example:

const OtherComponent = React.lazy(() => import('./OtherComponent'));

function MyComponent() {
return (
<Suspense fallback={<div>Loading...</div>}>
<OtherComponent />
</Suspense>
);
}

Babel Plugins for Optimization

Babel offers various plugins that can optimize the transformed code, such as minification, dead code elimination, and more.

Example: Using babel-preset-minify:

{
"presets": ["@babel/preset-env", "@babel/preset-react", "minify"]
}

Common Mistakes and How to Avoid Them

Understanding common pitfalls when working with JSX can save time and prevent errors.

Not Closing JSX Tags Properly

Every JSX tag must be properly closed. Forgetting to close tags can lead to compilation errors.

Incorrect:

const element = <img src="image.png">;

Correct:

const element = <img src="image.png" />;

Using class Instead of className

Since class is a reserved keyword in JavaScript, JSX uses className to assign CSS classes.

Incorrect:

const element = <div class="container"></div>;

Correct:

const element = <div className="container"></div>;

Embedding Expressions Without Curly Braces

JSX allows embedding JavaScript expressions within curly braces {}. Forgetting them can lead to unexpected behavior.

Incorrect:

const element = <h1>Hello, name!</h1>;

Correct:

const element = <h1>Hello, {name}!</h1>;

Returning Multiple Elements Without a Parent

A React component must return a single parent element. Wrapping multiple elements within a parent like <div> or using React fragments is necessary.

Incorrect:

const MyComponent = () => {
return (
<h1>Hello</h1>
<p>World</p>
);
};

Correct:

const MyComponent = () => {
return (
<>
<h1>Hello</h1>
<p>World</p>
</>
);
};

Must Read:

Conclusion

JSX is a very effective way of writing React components because it helps the developers to incorporate familiar HTML within JavaScript. Understanding this flow of conversion is imperative for the optimization of the applications built using React and the rectification of possible problems that may arise.

Babel is at the center of this transformation process, which begins from the parse of JSX to the creation of AST to the call of React.createElement and finally, the executable code in JavaScript. With even more increasing improvement and optimization, still JSX is used in the React platform to increase efficiency of the developers and the performance of the applications.

If one is able to comprehend the transformation of JSX, is in possession of the best practices and is certified against the common mistakes that developers make, there is off no doubt that the possibility of developing effective, manageable and fast React applications will be achieved.


Next Article

Similar Reads