This guide walks you through what JSX is, why we use it, and how to get started.
What Is JSX?
JSX (JavaScript Syntax Extension or JavaScript XML) is an extension to JavaScript. It provides an easier way to create UI components in React.
Here’s an example of its syntax:
const element = <h1>Hello, World!</h1>;
What comes after the equals sign isn’t a string or HTML, rather JSX. It doesn’t render out to HTML directly but instead renders to React Classes.
JSX is what we call Syntactic Sugar. A syntax created purely to programming easier to read and write for the developer – to make life sweeter. Under the hood JSX is simply turning the above code into a much more verbose class using the traditional React.createElement((component, props, ...children)))
method:
React.createElement(
"h1",
null,
"Hello, World!"
)
)
JSX isn’t only recommended by the React team because it saves you time. It was also created to help combine markup and logic into components, work with TypeScript to provide stricter data typing, and improve security.
How Does It Work?
JSX is still just JavaScript with some extra functionality. With JSX, you can write code that looks very similar to HTML or XML, but you have the power of seamlessly mixing JavaScript methods and variables into your code. JSX is interpreted by a transpiler, such as Babel, and rendered to JavaScript code that the UI Framework (React, in this case) can understand.
Note: you can use the Babel REPL to convert any of the following examples to regular JavaScript.
Don’t like JSX? That’s cool. It’s technically not required, and the React docs actually include a section on using React Without JSX. Let me warn you right now, though, it’s not pretty. Don’t believe me? Take a look.
JSX:
class SitePoint extends Component {
render() {
return (
<div>My name is <span>{this.props.myName}</span></div>
)
}
}
React Sans JSX:
class SitePoint extends Component {
render() {
return React.createElement(
"div",
null,
"My name is",
React.createElement(
"span",
null,
this.props.myName
)
)
}
}
Sure, looking at those small example pieces of code on that page you might be thinking, “Oh, that’s not so bad, I could do that.” But could you imagine writing an entire application like that?
The example is just two simple nested HTML elements, nothing fancy. Basically, just a nested Hello World
equivalent. Trying to write your React application without JSX would be extremely time consuming and, if you’re like most of us other developers out here working as characters in DevLand™, it will very likely quickly turn into a convoluted spaghetti code mess. Yuck!
Using frameworks and libraries and things like that are meant to make our lives easier, not harder. I’m sure we’ve all seen the overuse and abuse of libraries or frameworks in our careers, but using JSX with your React is definitely not one of those cases.
Why Use JSX?
There are several reasons why JSX is a good idea:
It has a low barrier to entry. JSX is as close to plain HTML and CSS as it currently gets. With JSX, you can easily embed pieces of JavaScript in your templates without having to learn an additional templating language and having to deal with complex levels of abstraction. Any person familiar with HTML, CSS, and JavaScript should have no problem reading and understanding JSX templates.
TypeScript support. TypeScript supports the compilation of TSX files with type-checking. This means that, if you make a mistake in the name of an element or an attribute type, the compilation will fail and you’ll see an error message pointing to your mistake. Popular IDEs such as VS Code also support TSX files and provide code-completion, refactoring, and other useful features.
Security. JSX takes care of the usual output sanitization issues to prevent attacks such as cross-site scripting.
What about a Separation of Concerns?
There’s a widespread belief that mixing HTML and JavaScript breaks the sacred separation of concerns principle. This judgment assumes that there’s a clear separation between HTML — which is responsible for the presentation — and JavaScript — which is responsible for application and business logic. However, this separation is based on technology, not on their concerns. JavaScript that’s responsible for rendering a list of items still belongs to the presentation layer and should be kept closer to the template than to the rest of the application.
By using JavaScript, we embrace the fact that the border should be drawn not between HTML and JavaScript, but rather between presentation logic and application logic, regardless of the languages used on either side. Focusing on this prevents us from mixing presentational JavaScript with business logic, thus enforcing the separation of concerns, reducing coupling, and improving maintainability.
Using JSX With React
Let’s start with the basics. As mentioned before, JSX needs to be transpiled into regular JavaScript before it can be rendered in the browser. Therefore, if you wish to follow along with the examples, you should have a React app already set up.
The following examples all come with runnable CodePen demos, so if all you want is to have a quick play around with the code, this might be a good option for you.
Otherwise, you could opt for Facebook’s Create React App tool. To use this, you’ll need to have Node and npm installed. If you haven’t, head to the Node.js download page and grab the latest version for your system (npm comes bundled with Node). Alternatively, you can consult our tutorial on installing Node using a version manager.
With Node installed, you can create a new React app like so:
npx create-react-app myapp
This will create a myapp
folder. Change into this folder and start the development server like so:
cd myapp
npm start
Your default browser will open and you’ll see your new React app. For the purposes of this tutorial, you can work in the App
component, which is located at src/App.js
.
Now let’s get into some code.
Basic Expressions
JSX is extremely similar to plain HTML and uses the same XML-based syntax. Here’s the canonical “Hello, World” example to start with:
const element = <h1>Hello, World!</h1>;
ReactDOM.render(element, document.getElementById('root'));
See the Pen
jsx-hello-world by SitePoint (@SitePoint)
on CodePen.
Note how the <h1>
element is used directly inside regular JavaScript. There are no quotes around it, since it’s not a string, but a language expression.
Similarly, you can use JavaScript in JSX tags by surrounding them with curly brackets:
function getGreeting(name) {
return `Hello, ${name}`;
}
const element = <h1>{getGreeting('John')}</h1>;
ReactDOM.render(element, document.getElementById('root'));
See the Pen
jsx-hello-world-with-js by SitePoint (@SitePoint)
on CodePen.
You can also use JavaScript expressions when specifying attribute values, such as passing an object containing inline styles in this example. This is useful when you want to pass a dynamic attribute value:
const styles = {
color: 'red',
fontStyle: 'italic'
}
const element = <h1 style={styles}>Hello, World!</h1>;
ReactDOM.render(element, document.getElementById('root'));
See the Pen
jsx-hello-world-styled by SitePoint (@SitePoint)
on CodePen.
Note: if you need to pass a dynamic list of attributes, you can use the spread operator: <h1 {...attributes}></h1>
.
Of course, as with regular HTML, JSX elements can contain children. Those can be string literals, other elements, or JavaScript expressions:
function getGreeting() {
return (
<h2>Welcome to the website</h2>
)
}
const element = <div>
<h1>Hello!</h1>
{getGreeting()}
</div>;
ReactDOM.render(element, document.getElementById('root'));
See the Pen
jsx-children by SitePoint (@SitePoint)
on CodePen.
Conditional Statements
The fact that you can embed JavaScript expressions and pass around JSX elements opens up many possibilities for structuring your code. A frequent use case is conditionally displaying an element to a logged-in user — such as a personalized message — or a validation error. JSX does not support standard if
statements, but you can use the ternary operator:
const loggedIn = true;
const element = <div>
<h1>Hello!</h1>
<h2>
{(loggedIn) ? 'Welcome back' : 'Nice to meet you'}
</h2>
</div>;
ReactDOM.render(element, document.getElementById('root'));
See the Pen
jsx-conditional-example by SitePoint (@SitePoint)
on CodePen.
An expression can return false
, true
, null
or undefined
to avoid rendering an element. Returning some falsy values, such as 0
or an empty string, will still render the element:
const error = true;
const element = <div>
<label>
Name:
<input />
{error ? <div style={{color: 'red'}}>Name invalid</div> : null}
</label>
</div>;
ReactDOM.render(element, document.getElementById('root'));
See the Pen
jsx-conditional-display by SitePoint (@SitePoint)
on CodePen.
Note the double curly braces used in the style
attribute. This the syntax for passing an inline object as the value: the outer pair denotes the expression and the inner one is the object itself.
In the above snippet, we see this:
{error ? <div style={{color: 'red'}}>Name invalid</div> : null}
This can be shortened even further, to this:
{error && <div style={{color: 'red'}}>Name invalid</div>}
This works because in JavaScript, true && expression
always evaluates to expression
, and false && expression
always evaluates to false
.
But although this pattern is fairly common, don’t forget about readability. Stick to code conventions that are agreed upon and understood by your team. Also, don’t overdo it with the nesting of conditional constructs. Often people put one ternary operator into another to save a couple of lines of code at the expense of readability. Refactor such code by extracting blocks into separate variables or functions.
Loops
Another frequent use case is to render a list of repeating elements. With JSX, you can’t use for
loops, but you can iterate over an array using the array map() method. For example, here’s a simple way to render a list of items:
const items = [
'Bread',
'Milk',
'Eggs'
]
const element = <div>
Grocery list:
<ul>
{items.map(item => <li>{item}</li>)}
</ul>
</div>;
ReactDOM.render(element, document.getElementById('root'));
See the Pen
jsx-map by SitePoint (@SitePoint)
on CodePen.
Obviously, you can use other array methods in the code as well, and it might be tempting to slip in some filtering logic or other calculations. Don’t give in to this! Remember the separation of concerns principle and separate this logic from the rendering code. This will make your code easier to read, understand, and test.
Custom Components
The two upcoming sections are more specific to React, but it’s still worth talking through them to get a good understanding of how everything fits together.
The prior code examples are extremely simplistic, since they only render a small set of standard HTML elements. In reality, your application will consist of custom components that will contain your application-specific view and logic. React allows you to define custom components and use them in markup as regular HTML elements. A custom element can be defined either as a function or an ES6 class.
Note: by React’s naming conventions, custom elements need to start with a capital letter, to distinguish them from standard elements.
function FunctionComponent() {
return <h2>This is a function component.</h2>
}
class ClassComponent extends React.Component {
render() {
return <h2>This is a class component.</h2>
}
}
const element = <div>
<FunctionComponent />
<ClassComponent />
</div>;
ReactDOM.render(element, document.getElementById('root'));
See the Pen
jsx-custom-components by SitePoint (@SitePoint)
on CodePen.
Event Handling
JSX provides a way to bind events similar to regular HTML. You can define a property on an element (the same property names as for regular HTML but camelCased) and pass a function as a value. In React, the callback function will receive a SyntheticEvent object as a first parameter, which is an abstraction on top of the regular browser event object:
function handleEvent(e) {
alert('Button clicked!');
console.log(e);
}
const element = <button onClick={handleEvent}>Test click</button>;
ReactDOM.render(element, document.getElementById('root'));
See the Pen
jsx-events by SitePoint (@SitePoint)
on CodePen.
Note: pay attention to the value of this
when passing around event handlers. When you define your component as an ES6 class, you usually define event handlers as methods of the class. Methods passed by value are not bound to a specific this
value, so to keep the current context, you need to explicitly bind them. See React’s documentation for more details on how to do this.
Not Just for React
JSX with React is pretty great stuff. But what if you’re using another framework or library, but still want to use it? Well, you’re in luck — because JSX technically isn’t tied to React. It’s still just DSL or “syntax sugar”, remember? Here are some other projects that use JSX:
- You can use JSX in Vue’s
render
function with the help of the @vue/babel-preset-jsx Babel preset. - Some other frameworks that position themselves as minimalist React-compatible alternatives such as Preact, Inferno or Hyperapp use JSX for their rendering layer.
- MDX allows you to use JSX in Markdown files to add interactive JS elements.
I hope this introduction to JSX helped to give you a better understanding of just what JSX is, how it can help you, and how it can be used to create your applications. Now get back out there and make some cool stuff!