An Introduction to JSX

An Introduction to JSX

An Introduction to JSX – SitePoint

Skip to main content

Free JavaScript Book!

Write powerful, clean and maintainable JavaScript.

RRP $11.95

When React was first introduced, one of the features that caught most people’s attention (and drew the most criticism) was JSX. If you’re learning React, or have ever seen any code examples, you probably did a double-take at the syntax. What is this strange amalgamation of HTML and JavaScript? Is this even real code?

Let’s take a look at what JSX is, how it works, and why the heck we’d want to be mixing HTML and JS in the first place!

What Is JSX?

Defined by the React docs as an “extension to JavaScript” or “syntax sugar for calling React.createElement(component, props, ...children))“, JSX is what makes writing your React Components easy.

JSX is considered a domain-specific language (DSL), which can look very similar to a template language, such as Mustache, Thymeleaf, Razor, Twig, or others.

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 that are consumed by the Virtual DOM. Eventually, through the mysterious magic of the Virtual DOM, it will make its way to the page and be rendered out to HTML.

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!

Leave a Reply

Your email address will not be published. Required fields are marked *