React 101: JSX
I started with React a month ago and this is my very first javascript framework. Very confusing to start with, but I am beginning to like it and hence documenting my learnings as I go along. I will write a separate post for the components.
const h1 = <h1>Hello World</h1>
Intro to JSX
JSX is a syntax extension for JavaScript. It was written to be used with React and the code looks a lot like HTML.
‘Syntax extension’ means that JSX is not valid JavaScript. Web browsers can’t read it. The Javascript file containing JSX code will need to be compiled. That means that before the file reaches a web browser, a JSX compiler will translate any JSX into regular JavaScript.
JSX Element
A basic unit of JSX is called JSX element which looks like HTML but is written in a JavaScript file.
<h1>Hello World</h1>
JSX elements are treated as JavaScript expressions. They can go anywhere that JavaScript expressions can go.
/**Stored in variable */
const navBar = <nav>I am a nav bar</nav>;
/**Stored in an object */
const myTeam = {
center: <li>Benzo Walli</li>,
powerForward: <li>Rasha Loa</li>,
smallForward: <li>Tayshaun Dasmoto</li>,
shootingGuard: <li>Colmar Cumberbatch</li>,
pointGuard: <li>Femi Billon</li>
};
Attributes in JSX
A JSX attribute is written using HTML-like syntax: a name, followed by an equals sign, followed by a value.
<a href='http://www.example.com'>Welcome to the Web</a>;
const title = <h1 id='title'>Introduction to React.js: Part I</h1>;
Nested JSX
You can nest JSX elements inside of other JSX elements, just like in HTML.
Here’s an example of a JSX <h1>
element, nested inside of a JSX <a>
element:
<a href="https://www.example.com">
<h1>
Click me!
</h1>
</a>
If a JSX expression takes up more than one line, it is then wrapped in parentheses.
Nested JSX expressions can be saved as variables, passed to functions, etc., just like non-nested JSX expressions can!
const theExample = (
<a href="https://www.example.com">
<h1>
Click me!
</h1>
</a>
);
JSX Outer Elements
A JSX expression must have exactly one outermost element
The code below will work:
const paragraphs = (
<div id="i-am-the-outermost-element">
<p>I am a paragraph.</p>
<p>I, too, am a paragraph.</p>
</div>
);
But this code will not work:
const paragraphs = (
<p>I am a paragraph.</p>
<p>I, too, am a paragraph.</p>
);
The first opening tag and the final closing tag of a JSX expression must belong to the same JSX element!
If a JSX expression has multiple outer elements, the solution is usually: to wrap the JSX expression in a <div</<div>
or with the new concept React Fragments: <></>
.
Rendering JSX
To render a JSX expression means to make it appear onscreen.
React renders HTML to the web page by using a function called ReactDOM.render()
.
ReactDOM
is the name of a JavaScript library. This library contains several React-specific methods, all of which deal with the DOM in some way or another.
ReactDOM.render()
is the most common way to render JSX. It takes a JSX expression, creates a corresponding tree of DOM nodes, and adds that tree to the DOM. That is the way to make a JSX expression appear onscreen.
The ReactDOM.render()
function takes two arguments, a JSX expression, and an HTML element to which the first argument gets appended.
ReactDOM.render(<h1>Hello world</h1>, document.getElementById('app'));
There is an index.html file in the React project that will have a code like below. This element acts as a container for ReactDOM.render()
‘s first argument!
<body>
<main id="app">
//Code is rendered here
</main>
</body>
Passing a Variable to ReactDOM.render()
ReactDOM.render()
‘s first argument should evaluate to a JSX expression, it doesn’t have to literally be a JSX expression.
The first argument could also be a variable, so long as that variable evaluates to a JSX expression.
const toDoList = (
<ol>
<li>Finish JSX Lesson</li>
<li>Write an article on React 101</li>
</ol>
);
ReactDOM.render(
toDoList,
document.getElementById('app')
);
The Virtual DOM
One special thing about ReactDOM.render()
is that it only updates DOM elements that have changed.
React accomplishes this using a concept called the virtual DOM.
In React, for every DOM object, there is a corresponding “virtual DOM object.” A virtual DOM object is a representation of a DOM object, like a lightweight copy.
A virtual DOM object has the same properties as a real DOM object, but it lacks the real thing’s power to directly change what’s on the screen.
Manipulating the DOM is slow. Manipulating the virtual DOM is much faster because nothing gets drawn onscreen.
When you render a JSX element, every single virtual DOM object gets updated.
This sounds incredibly inefficient, but the cost is insignificant because the virtual DOM can update so quickly.
Once the virtual DOM has been updated, then React compares the virtual DOM with a virtual DOM snapshot that was taken right before the update.
By comparing the new virtual DOM with a pre-update version, React figures out exactly which virtual DOM objects have changed. This process is called “diffing.”
Once React knows which virtual DOM objects have changed, then React updates those objects, and only those objects, on the real DOM. This process is called ‘reconciliation’
This makes a big difference! React can update only the necessary parts of the DOM.
In summary, here’s what happens when you try to update the DOM in React:
- The entire virtual DOM gets updated.
- The virtual DOM gets compared to what it looked like before you updated it. React figures out which objects have changed.
- The changed objects, and the changed objects only, get updated on the real DOM.
- Changes on the real DOM cause the screen to change.
Click for the Difference between virtual dom and dom
class vs className
In HTML, it's common to use class
as an attribute name:
<h1 class="big">Hey</h1>
In JSX, className
is used instead
<h1 className="big">Hey</h1>
When JSX is rendered, JSX className
attributes are automatically rendered as class
attributes. An Example
const myDiv = <div className="big">I AM A BIG DIV</div>
ReactDOM.render(myDiv, document.getElementById('app'));
Self-Closing Tags
When you write a self-closing tag in HTML, it is optional to include a forward slash immediately before the final angle bracket.
But, in JSX, you have to include the slash. If you write a self-closing tag in JSX and forget the slash, you will raise an error:
// Fine in HTML with a slash // Also fine in JSX
<br />
// Fine, without the slash in HTML // NOT FINE IN JSX
<br>
Variables in JSX
Regular Javascript can be easily written inside a JSX expression in the JavaScript file but it is accessed with curly braces. This will display 2+3 in the browser
import React from 'react';
import { createRoot } from 'react-dom/client';
const container = document.getElementById('app');
const root = createRoot(container);
root.render(<h1>2 + 3</h1>);
Any code in between the tags of a JSX element will be read as JSX, not as regular JavaScript! JSX doesn’t add numbers — it reads them as text, just like HTML.
<h1>{2 + 3}</h1>
Everything inside of the curly braces will be treated as regular JavaScript.
You can access variables while inside of a JSX expression, even if those variables were declared outside of the JSX code block.
// Declare a variable:
const name = 'Henna';
// Access your variable inside of a JSX expression:
const greeting = <p>Hello, {name}!</p>;
Variable Attributes in JSX
It’s common to use variables to set attributes
// variable to set the `height` and `width` attributes:
const sideLength = "200px";
const panda = (
<img
src="images/panda.jpg"
alt="panda"
height={sideLength}
width={sideLength} />
);
Object properties are often used to set attributes:
const pics = {
panda: "https://shorturl.at/qKLXZ",
owl: "https://shorturl.at/vyDW6",
owlCat: "https://shorturl.at/qEKX0"
};
const panda = (
<img
src={pics.panda}
alt="Lazy Panda" />
);
const owl = (
<img
src={pics.owl}
alt="Unimpressed Owl" />
);
const owlCat = (
<img
src={pics.owlCat}
alt="Ghastly Abomination" />
);
Event Listeners in JSX
JSX elements can have event listeners, just like HTML elements can. Programming in React means constantly working with event listeners.
function clickAlert() {
alert('You clicked this image!');
}
<img onClick={clickAlert} />
An event listener attribute’s value is a function.
Note that in HTML, event listener names are written in all lowercase, such as onclick
or onmouseover
. In JSX, event listener names are written in camelCase, such as onClick
or onMouseOver
.
JSX Conditionals: If Statements don't work in the JSX expression
The following code will break
(
<h1>
{
if (purchase.complete) {
'Thank you for placing an order!'
}
}
</h1>
)
JSX Conditionals: Statements that work
One option is to write an if
statement but not inject it into JSX.
if (user.age >= drinkingAge) {
message = (
<h1>
Hey, check out this alcoholic beverage!
</h1>
);
} else {
message = (
<h1>
Hey, check out these earrings I got at Claire's!
</h1>
);
}
JSX Conditionals: Ternary Operator
The ternary operator works the same way in React as it does in regular JavaScript. However, it shows up in React surprisingly often.
const headline = (
<h1>
{ age >= drinkingAge ? 'Buy Drink' : 'Do Teen Stuff' }
</h1>
);
JSX Conditionals: &&
&&
works best for conditionals that will sometimes do an action but other times do nothing at all.
const tasty = (
<ul>
<li>Applesauce</li>
{ !baby && <li>Pizza</li> }
{ age > 15 && <li>Brussels Sprouts</li> }
{ age > 20 && <li>Oysters</li> }
{ age > 25 && <li>Grappa</li> }
</ul>
);
If the expression on the left of the &&
evaluates as true, then the JSX on the right of the &&
will be rendered. If the first expression is false, however, then the JSX to the right of the &&
will be ignored and not rendered.
.map in JSX
Using .map()
is the most efficient way to create a list of JSX elements.
const strings = ['Home', 'Shop', 'About Me'];
const listItems = strings.map(string => <li>{string}</li>);
<ul>{listItems}</ul>
Keys
A list in JSX sometimes would need a key to render the list. A key
is a JSX attribute. The value should be unique.
keys
don’t do anything visible! React uses them internally to keep track of lists. If you don’t use keys when you’re supposed to, React might accidentally scramble your list items into the wrong order.
Not all lists need to have keys
. A list needs keys
if either of the following is true:
- The list items have a memory from one render to the next. For instance, when a to-do list renders, each item must “remember” whether it was checked off. The items shouldn’t get amnesia when they render.
- A list’s order might be shuffled. For instance, a list of search results might be shuffled from one render to the next.
const people = ['Rowe', 'Prevost', 'Gare'];
const peopleList = people.map( (person,i) =>
<li key={'person_' + i}>{person}</li>
);
React.createElement
React code can be written without using JSX at all. The following JSX expression
const h1 = <h1>Hello world</h1>;
can be rewritten without JSX, like this:
const h1 = React.createElement(
"h1",
null,
"Hello world"
);
When a JSX element is compiled, the compiler transforms the JSX element into the method that you see above: React.createElement()
. Every JSX element is secretly a call to React.createElement()
.
React docs for more info.
That is all folks! In the next article, I wrote about React Components.