Understanding React elements and JSX
Franco D'Alessio
April 10, 2020 • 8 min. readLet’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>
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');
Then create a new div and add the text content:
const element = document.createElement('div');
element.textContent = 'Hello World';
And finally append this new child element to the root element:
rootElement.appendChild(element);
That’s all we need to display a Hello World message. Here is the final code:
<!DOCTYPE html>
<html>
<head>
<title>Hello World</title>
<meta charset="UTF-8" />
</head>
<body>
<div id="root"></div>
<script type="text/javascript">
const rootElement = document.getElementById("root");
const element = document.createElement("div");
element.textContent = "Hello World";
rootElement.appendChild(element);
</script>
</body>
</html>
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 can get react
and react-dom
from unpkg:
<script src="https://unpkg.com/react@16.12.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.12.0/umd/react-dom.development.js"></script>
Then, instead of creating a div
element we create a React element. The API for react.createElement
is:
function createElement(elementType, props, ...children) {}
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');
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'});
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);
The end result will be the same as the first example. This is the final code:
<!DOCTYPE html>
<html>
<head>
<title>Hello World</title>
<meta charset="UTF-8" />
</head>
<body>
<div id="root"></div>
<script src="https://unpkg.com/react@16.12.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.12.0/umd/react-dom.development.js"></script>
<script type="text/javascript">
const rootElement = document.getElementById("root");
const element = React.createElement("div", null, "Hello World");
ReactDOM.render(element, rootElement);
</script>
</body>
</html>
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>;
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 usereact.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')
);
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')
);
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>
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>;
}
Specifying attributes
You can use quotes to specify string literals as attributes:
const element = <img src="http://xyz.com/img.jpg"></img>;
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>;
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} />;
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 ❤️