7 - JSX

JSX (JavaScript Syntax Extension and occasionally referred to as JavaScript XML) is an extension to the JavaScript language syntax which provides a way to structure component rendering using syntax familiar to many developers, commonly used in React. It is similar in appearance to HTML. React components are typically written using JSX, although they do not have to be, as components may also be written in pure JavaScript. JSX is created by Meta (formerly Facebook). It is similar to another extension syntax created by Meta for PHP called XHP. (Credit: Wiki)

Theoretically, JSX is not related to React and nor invented by React. But React's entire paradigm revolves around JSX. It'd be practically impossible to find a React app that doesn't use JSX. Due to the tight coupling of React and JSX, sometimes it is believed that React invented JSX, which is not right, of course.

JSX is the second pillar in the foundation of React.

Though being popular, JSX is not a standard. Browsers don't understand it. All the React apps need a transpiler like Babel to convert JSX to JS (we've already seen it in the previous section).

JSX is a syntax much like XML/HTML that can co-exist with JavaScript code. This means we can write HTML like content and combine it with JavaScript. This is a very different paradigm. A very powerful one, though.

Traditionally, we would write HTML files that contains/includes JS files. This is how we've built the file.io app in vanilla JS. There are two HTML files: upload.html and download.html. These HTML files include relevant JS files like upload.js and download.js.

This design gets reversed in the React world. The reason for that is JSX. With JSX, we write a JS file that has HTML inside it. Except for index.html, you won't see any other .html files inside React code. For example - in the function component, we wrote a JS file that returns s JSX (which gets converted to HTML).

It is important to learn the distinction at this point. We'll repeat it one more time. In the traditional world, HTML files include JavaScript code. In the React world, JS files return HTML code.

The last section (section 6) ended with an application that contains two components: Component1 and Component2. Let's use them to write a more advanced app that shows a contact card with a button to buy a dummy pizza. While writing the app, we'll learn some JSX along the way. There is no need for Component2, so that has been removed.

Contact card

To start with, the Component1 gets renamed to Card. The Card component will contain a main div that contains a left and a right part. The left part will show a contact image, while the right part will show the contact details. The left side is called CardImage and the right side is called CardDetails.

The start is always App.js (that's the usual, although you're free to call it whatever you like). The App component will contain Card, that'll contain CardImage and CardDetails.

import './App.css';
import Card from './components/Card';

function App() {
  return (
    <div className="App">
        <Card />
    </div>
  );
}

export default App;

This is something that we've already seen in the previous section, where we were including Component1 and Component2 inside App. There are a couple of important points to make here:

  • JSX need special names for attributes like class becomes className, onclick becomes onClick, onmouseover becomes onMouseOver. In short, all attribute names become camel case where it is applicable.

return (
  <button className="some-class" onClick=/*specify handler*/ onMouseOver=/*specify handler*/>Click me!</button>
);
  • JSX can't have siblings at componet root level. There is always a single root for that component. If there are siblings at root level, it'll result in compilation error. As a quick solution, you can always wrap the entire contents of the component inside a plain div.

// Not allowed ==>

return (
  <button>Button 1</button>
  <button>Button 2</button>
);

// Allowed ==>

return (
  <div>
    <button>Button 1</button>
    <button>Button 2</button>
  </div>
);

Now let's move on to the Card component. This component contains two child components:

  • CardImage

  • CardDetails

The child components can be imported and used in the Card JSX:

There is nothing new to learn in the Card component. Let's move on to the CardImage & CardDetails components. Before adding real text, first we'll create two dummy divs that simply shows the left side and the right side.

Again, we're comfortable so far. Nothing new yet. Both the child components return a dummy div. Before moving on, let's take a look at the UI:

Looks good. Now let's move on and finish the left side, which only displays an image. We're using https://kristalle.com/wp-content/uploads/2020/07/dummy-profile-pic-1.jpg as the profile pic. A small CSS change is required to fit the image inside the div. The image turns out to be larger than our needs, but this book is not about learning CSS, so we'll leave it like that.

Let's take a quick look at our work so far.

Well, not bad at all. Again, the left side became bigger than how we thought it to be. But we'll ignore that.

On the right side, let's display name, phone & city. There are two ways to add values into the JSX:

  • Add them directly: You can always put the data directly in the JSX. This is good for static values like page heading, footer, section title, etc.

return (
  <div>
    <button>Click me!</button>  
  </div>
);

In the above example, the button label is static. It is not expected to change.

  • Add them through JS: The other way is to add variable data into JSX is by embedding JS code into JSX through the use of curly braces {}. Anything inside the curly brace is evaluated as a JavaScript expression. The contents inside {} could be a simple JS variable or complex conditions.

function Comp1() {
  const v = 'Click here!';
  
  return (
    <div>
      <button>{v}</button>  
    </div>
  );
}

The {v} inside JSX is evaluated as a JS expression at runtime. In this case, it evaluates to a simple variable.

Let's apply this knowledge to the right side of the contact card. We'll have variables for name, phone and city. These variables will be used directly in the JSX (just like {v}). There is no need to have separate variables for name, city, and phone. They can also be inside an object. Anything inside {} is evaluated as a JS expression, so objects are fine too.

Let's take a quick look at our work so far.

The contact card is taking shape quite nicely. Again, not much consideration for look-n-feel because this is not a book on styling.

Conditional Display

We've just seen the use case of the JS expressions inside {} as a data source. One other use case of the JS expressions inside {} is to conditionally display something. The common way to conditionally display something is to use the short circuit style of JS coding (&&, ||).

function A() {
  const a = true;

  return (
    <div>
      {a && <h1>A is true</h1>}
    </div>
  );
}

You should pay special attention to a single line: {a && <h1>A is true</h1>}. This is a very common way to conditionally render in React. As you're familiar with JS, you would have already used short-circuiting. If the variable a is true, then the right part of the expression gets executed. This means that, if the variable a is true, then the h1 will make it to the page. In the JSX world, it is allowed to use JSX inside {} mixed with regular JS code. It is something like this:

Let's apply this knowledge to the contact card we're building. We'll add an extra attribute called donate. If donate is true, a button will be displayed to buy a pizza. First, let's update the CardDetails component without setting the donate variable.

Let's test it out before adding the donate attribute:

Now, we can add the donate attribute and set it to true.

Let's check if the button appears:

The button does appear as soon as donate attribute is set. In real cases, the data would likely come from an API call, so it makes total sense to use {} inside the JSX code.

Event handlers

Finally, we'll add a handler for the button we've just enabled for this contact card. When the button is clicked, we'll just show an alert. This requires adding a click handler for the button. Any JS function can be assigned as the click handler through the onClick attribute in JSX. The syntax is onClick={someFunc}. This is enough. Note that quotes are not required around {}.

Here is a quick test of the button click:

--

This was a very brief introduction to JSX. No attempt has been made to create a comprehensive JSX guide. There are tons of resources on Google to help learn JSX. We've only covered parts of JSX that'd be useful in building the file.io service. In the next section, we'll start decomposing the vanilla file.io app into React components.

Last updated