DEV Community

Franco D'Alessio
Franco D'Alessio

Posted on • Edited on

Understanding React elements and JSX

Photo by Ferenc Almasi on Unsplash

Let’s start by writing a simple piece of code to display a “Hello World” message, using just vanilla Javascript and browser APIs.

First, let’s create a root div in our body section:



<body>
  <div id="root"></div>
</body>


Enter fullscreen mode Exit fullscreen mode

We will now create a new div with the Hello World message and append it to our root div using Javascript.

We need to get that root div element first:



const rootElement = document.getElementById('root');



Enter fullscreen mode Exit fullscreen mode

Then create a new div and add the text content:



const element = document.createElement('div');
element.textContent = 'Hello World';


Enter fullscreen mode Exit fullscreen mode

And finally append this new child element to the root element:



rootElement.appendChild(element);


Enter fullscreen mode Exit fullscreen mode

That’s all we need to display a Hello World message. Here is the final code:

Let’s do the same with React

React controls and updates the DOM using the same APIs we used in our previous example. But instead of creating DOM elements, we’ll create React elements. react-dom will take care of converting them into DOM elements and putting them into the page.

What is a React element?

Think about React elements as a description of what you see on the screen. React reads these objects and uses them to construct the DOM and keep it up to date.

Don’t confuse React elements with components. Elements are what components are “made of”, and you must first understand what they are before jumping ahead into components.

The createElement API

For this first React example we’ll use React’s createElement API.

We need to get React on the page. We'll add react and react-dom directly from unpkg as script tags.

Then, instead of creating a div element we create a React element. The API for react.createElement is:



function createElement(elementType, props, ...children) {}


Enter fullscreen mode Exit fullscreen mode

We don’t have any props in our example, so we’d create our element like this:



const element = React.createElement("div", null, 'Hello World');


Enter fullscreen mode Exit fullscreen mode

The text Hello World is our element’s child.

We can see this React element by logging it to the console:

We don’t get a DOM element, but an object. Remember we said earlier that React elements are objects that describe what you see on the screen.

You can see that children is actually inside the props object.

These two lines are equivalent and both correct:



const element = React.createElement("div", null, 'Hello World');
const element = React.createElement("div", {children: 'Hello World'});


Enter fullscreen mode Exit fullscreen mode
You can pass the children inside the props object or as the third parameter of the function.

Ok, we’ve got our React element. Now what?

Instead of appending this element to the root element, as we did in the first example with our DOM element, we’ll let react-dom handle all that:



ReactDOM.render(element, rootElement);


Enter fullscreen mode Exit fullscreen mode

The end result will be the same as the first example. This is the final code:

Finally, let’s use JSX! 🚀

This react.createElement syntax works, but is not the best. Fortunately, we have another option, which is also the standard way the community uses to create React elements.

What is JSX? 🤔

JSX is an extension to Javascript to support syntax that looks like the HTML code you would write to create these DOM elements.

So we can create our element by just doing this:



const element = <div>Hello World</div>;


Enter fullscreen mode Exit fullscreen mode

Sweet, right?

Why JSX?

React doesn’t require you to use JSX. You can use the createElement API and everything will work in the same way.

However, JSX is of great help. React is based on the principle that rendering logic is coupled with UI logic. Instead of separating them by putting markup and logic in separate files, React uses components that contain both.

Using JSX is helpful because it allows you to easily work with UI inside Javascript code.

JSX is awesome! But we still have a problem…

The browser does not understand JSX natively, so it needs to be compiled. That’s where Babel comes in. It will convert JSX syntax to something the browser can understand.

What do you think that will be?

Exactly: it will use react.createElement API.

You can try this yourself in the Babel’s website.

Adding props

In the last example, the second argument to createElement is null because we have no props.

We can include a className and see how Babel translates it to be the second argument of the createElement function:

Adding children

We can also add more children. Right now, the only child is the Hello World text, but we can add more:

You can see that now the third argument of the createElement function is not just a string. Instead it’s a second React element of type p, which has the Hello World string text as its child.

The power of JSX 💪

With JSX you can do more than just creating React elements. Let’s take a look at everything JSX has to offer.

Embedding expressions

Using curly braces, you can embed any Javascript expression inside JSX.

For example, you can do this:



const name = 'John';
const element = <div>Hello {name}</div>
ReactDOM.render(
 element,
 document.getElementById('root')
);


Enter fullscreen mode Exit fullscreen mode

And Hello John will be displayed on the page.

But it doesn’t have to be just a static string value, you can embed any Javascript expression:



const element = <div>2+2 = {2+2}</div>
ReactDOM.render(
 element,
 document.getElementById('root')
);


Enter fullscreen mode Exit fullscreen mode

In this case, 2+2 = 4 will be displayed on the page.

JSX is an expression

We know that JSX will be compiled to be a react.createElement function, and that function will return an object.

That means that we can assign JSX to variables:



const element = <div>Hello World</div>


Enter fullscreen mode Exit fullscreen mode

Or, for example, return JSX from functions:



const getAgeDescription = (age) => {
  if (age < 50) {
    return <h1>You're young</h1>;
  } 
  return <h1>You're old</h1>;
}


Enter fullscreen mode Exit fullscreen mode

Specifying attributes

You can use quotes to specify string literals as attributes:



const element = <img src='http://xyz.com/img.jpg'></img>;


Enter fullscreen mode Exit fullscreen mode

Or curly braces to embed a Javascript expression:



const user = { name: 'John', profileImgUrl: 'http://xyz.com/img.jpg' };
const element = <img src={user.profileImgUrl}></img>;


Enter fullscreen mode Exit fullscreen mode

JSX uses camelCase for attributes, and there’re some changes you have to keep in mind. As some words are reserved by Javascript, some attributes change its name when using JSX.

For example, you don’t use class in JSX, but className. You don’t use for in a label element, you use htmlFor .

To read more about these exceptions and all the accepted attributes in JSX you can check the official documentation.

Self-closing tags

If an element doesn’t have any children, you can close it with />:



const element = <img src={user.profileImgUrl} />;


Enter fullscreen mode Exit fullscreen mode

That’s all!

Understanding how JSX is compiled is important because it will make you more effective at using JSX. I encourage you to take you React code to the Babel website to see how it is compiled and how it looks using the createElement API.

I’ll leave this here. There are a lot of things I could continue writing about (rendering, components, etc.), but I’ll do so in separate articles. JSX is an important concept and you should understand it well before moving on to other stuff.

Thanks for reading ❤️

Top comments (0)