JSX looks like HTML, but it lives inside a JavaScript file. It is the way most React developers describe what a component should show. At first it feels strange to mix HTML and JavaScript. After a short time it feels natural, because the code that decides what to show and the code that shows it sit together.
What JSX really is
JSX stands for JavaScript XML. It is not HTML, and browsers cannot read it. Your build tool (Vite) changes it into plain JavaScript before the browser sees it. This line of JSX:
const title = <h1 className="big">Hello</h1>;
becomes a normal function call, roughly React.createElement('h1', { className: 'big' }, 'Hello'). You never need to write that by hand. JSX is just a friendly way to write it. Knowing this explains the rules below, because JSX follows JavaScript rules, not HTML rules.
Rule 1: return one parent element
A component can return only one thing. If you want to return two headings, wrap them in a parent. The parent can be a div, or a fragment, which is an empty tag that adds nothing to the page.
function Intro() {
return (
<>
<h1>Welcome</h1>
<p>Glad you are here.</p>
</>
);
}
The <> and </> are the fragment. Use a fragment when you do not want an extra div in your page. The round brackets after return let you write the JSX over many lines safely.
Rule 2: close every tag
In HTML you can write <br> or <img src="a.png"> with no closing. In JSX every tag must be closed. Either write a closing tag, or end the tag with a slash:
<img src="logo.png" alt="Company logo" />
<input type="text" />
<br />
Rule 3: use curly braces to show JavaScript
This is the most important JSX skill. Inside curly braces {} you can write any JavaScript expression, which is anything that gives a value. A variable, a calculation, a function call or a condition all work.
function Profile() {
const name = 'Asha';
const age = 24;
return (
<section>
<h2>{name}</h2>
<p>Next year I will be {age + 1}.</p>
<p>My name has {name.length} letters.</p>
<p>Shouting: {name.toUpperCase()}</p>
</section>
);
}
You can use curly braces in two places: as the content between tags (like {name} above), and as the value of an attribute, like src={imageUrl}. You cannot use them for the tag name, and you cannot put a statement such as if or for inside them. Statements do not give a value. Use a ?: expression instead. You will see this in the lesson on conditional rendering.
Rule 4: some attribute names are different
Because JSX is JavaScript, some HTML words are already taken by JavaScript. And all attribute names use camelCase, which means the first word is small and each next word starts with a capital letter.
classbecomes `className`, becauseclassis a JavaScript word.foron a label becomes `htmlFor`.onclickbecomes `onClick`, andonchangebecomes `onChange`.tabindexbecomes `tabIndex`, andmaxlengthbecomes `maxLength`.
Good news: if you forget, React shows a clear warning in the browser console that names the right word.
Styles as objects
The style attribute does not take a string in React. It takes an object, and the object has its own curly braces. That is why you see double braces: the outer pair means “JavaScript here”, and the inner pair is the object.
<p style={{ color: 'tomato', fontSize: '20px', marginTop: 10 }}>
Styled text
</p>
CSS names with a dash become camelCase (font-size becomes fontSize). Numbers are treated as pixels. For more than a few styles, use a CSS file instead, as lesson 10 shows.
Comments in JSX
Inside the tags you cannot use // or <!-- -->. Use curly braces and a normal comment:
<div>
{/* This comment will not show on the page */}
<p>Visible text</p>
</div>
Showing lists and objects
You can show strings and numbers directly. You can also show an array of strings, and React puts them next to each other. But you cannot show a plain object. If you try {user} where user is { name: 'Asha' }, React throws an error that says objects are not valid as a React child. Show the parts you want instead: {user.name}.
Values like true, false, null and undefined show nothing. This is useful for conditions, and it is also a trap: the number 0 does show. We will see this trap again in the conditional rendering lesson.
Components in JSX
Tags that start with a small letter, like div or p, are normal HTML elements. Tags that start with a capital letter, like Welcome or ProductCard, are your own components. That is why component names must start with a capital: it is how React tells them apart.
function Welcome() {
return <h2>Welcome!</h2>;
}
function App() {
return (
<div>
<Welcome />
<Welcome />
</div>
);
}
Common beginner mistakes
- Two parents: returning
<h1>and<p>side by side without a wrapper. Fix: wrap them in a fragment. - Forgetting to close a tag:
<input>must be<input />. - Using `class`: use
className. - Quotes around braces:
src="{url}"shows the text{url}. Remove the quotes. - Lowercase component:
<welcome />is treated as an HTML tag. Use<Welcome />. - Statements inside braces: you cannot write
{if (x) ...}. Use{x ? a : b}.
Walk through one component line by line
Let us read a small component slowly, as the browser and React would. Here it is again, with a bit more detail:
function Profile() {
const name = 'Asha';
const skills = ['React', 'CSS'];
return (
<section>
<h2>{name}</h2>
<p>I know {skills.length} things.</p>
</section>
);
}
- React calls the function
Profile(). It is just a normal function call. - The first two lines make two ordinary variables. There is nothing special about them yet.
- The
returngives back JSX. Vite has already changed it into function calls, so the result is a plain description of asectionwith anh2and ap. - When React meets
{name}, it runs the JavaScript inside the braces, gets the textAsha, and puts it in the heading. - For
{skills.length}, it works out the number 2 and shows it inside the sentence. - React then updates the real page so it matches this description.
Once you see JSX as “JavaScript that describes the page”, the rules stop feeling random. A tag name that starts with a capital letter is a function to call. Curly braces are a hole where JavaScript goes. And one parent is needed because a function can return only one value.
Your task
- Make a component
Cardwith a name, a job title and a year of birth stored in variables. Show them, and show the age using a calculation. - Add an image with
alttext taken from the name variable. - Give one heading an inline style with a colour and a bigger font size.
- Break a rule on purpose (remove a closing tag) and read the error message.
How to check it worked
- The card shows the name, the job title and a correct age.
- Your image has alt text that changes if you change the variable.
- You can say in your own words why
classisclassName.
Summary
- JSX is a way to write HTML-like code inside JavaScript. Vite turns it into plain JavaScript.
- Return one parent (or a fragment), close all tags, and use camelCase attributes such as
classNameandonClick. - Use
{}to show any JavaScript expression. The style attribute takes an object. - Component names start with a capital letter.