Setting up a React project with Vite
The mental model: how React renders (2)
JSX stands for JavaScript XML. It looks like HTML, but it's JavaScript in disguise. When Vite processes your files, it converts JSX into regular function calls before the browser ever sees it.
This:
const element = <h1 className="title">Hello</h1>;
Becomes this:
const element = React.createElement('h1', { className: 'title' }, 'Hello');
You'll never write React.createElement by hand. But knowing JSX compiles to a function call explains why some rules exist — a function can only return one value, which is why a component can only return one root element.
JSX looks close enough to HTML that you'll write it on autopilot most of the time. A handful of differences will catch you off guard until they don't.
| HTML | JSX | Why |
|---|---|---|
class="..." |
className="..." |
class is a reserved word in JS |
for="..." |
htmlFor="..." |
for is a reserved word in JS |
<img> |
<img /> |
All tags must be closed |
<br> |
<br /> |
Same — self-close it |
style="color: red" |
style={{ color: 'red' }} |
style takes a JS object |
tabindex |
tabIndex |
JSX uses camelCase for attributes |
onclick="..." |
onClick={...} |
camelCase + a function reference |
<!-- comment --> |
{/* comment */} |
JS comments wrapped in braces |
<aside> ⚠️
Warning
class and for are the two you'll forget most often because your muscle memory types them from HTML. TypeScript will catch them — a red squiggly and a clear error message. When you see "did you mean className?", that's why.
</aside>
{}Anywhere inside JSX, you can drop into JavaScript with curly braces. Anything that's an expression — something that resolves to a value — works inside them.
function Greeting() {
const name = 'Federico';
const hour = new Date().getHours();
const isMorning = hour < 12;
return (
<div className="greeting">
<h2>Hello, {name}!</h2>
<p>The current hour is {hour}.</p>
<p>2 + 2 = {2 + 2}</p>
<p>Time of day: {isMorning ? 'morning' : 'afternoon'}</p>
<p>Name in caps: {name.toUpperCase()}</p>
</div>
);
}
Things that work inside {}: variables, math, function calls, ternaries, other JSX, arrays of JSX elements.
Things that don't work: statements like if, for, while, or variable declarations. Statements don't return values, so JSX can't embed them. Do that work before the return and use the resulting variable in your JSX.
// ❌ Won't work — if is a statement
return (
<p>{if (isLoggedIn) { 'Welcome back' }}</p>
);
// ✅ Do the logic before the return
const message = isLoggedIn ? 'Welcome back' : 'Please log in';
return <p>{message}</p>;
<aside> ⚠️
Hands On
Write a ProfileCard component that displays:
birthYear variableUse {} to embed at least four JavaScript values.
</aside>
A component can only return one root element. This is invalid:
// ❌ Two siblings at the root
return (
<h1>Title</h1>
<p>Subtitle</p>
);
Two ways to fix it. Wrap in a parent element when the wrapper makes semantic sense:
return (
<div>
<h1>Title</h1>
<p>Subtitle</p>
</div>
);
Use a Fragment when you don't want an extra DOM node:
return (
<>
<h1>Title</h1>
<p>Subtitle</p>
</>
);
<> and </> is shorthand for <React.Fragment>. Reach for it when adding a <div> would break your HTML structure — inside a <ul> where only <li> is valid, for example, or when an extra wrapper would interfere with your CSS layout.
In JSX, the style attribute takes a JavaScript object. Keys are camelCase, values are strings — except for pixel values, which can be plain numbers.
// HTML
<div style="background-color: blue; font-size: 16px;">Hi</div>
// JSX
<div style={{ backgroundColor: 'blue', fontSize: 16 }}>Hi</div>
The double curly braces aren't special syntax. The outer {} drops into JavaScript. The inner {} is just an object literal.
We're using inline styles in these early lessons to keep things simple. Once you've got the basics down, we'll move to CSS files per component — which is the standard approach and what we'll use going forward.
function ProductCard() {
const product = {
title: 'Mechanical Keyboard',
price: 129.99,
inStock: true,
tags: ['electronics', 'office', 'gaming'],
};
const cardStyle = {
border: '1px solid #ddd',
borderRadius: 8,
padding: 16,
maxWidth: 300,
};
return (
<article style={cardStyle}>
<h3>{product.title}</h3>
<p>Price: €{product.price.toFixed(2)}</p>
<p>{product.inStock ? '✅ In stock' : '❌ Out of stock'}</p>
<small>Tags: {product.tags.join(', ')}</small>
</article>
);
}
<aside> ⌨️
Hands On
Fix all the errors in this broken JSX. There are five:
function BrokenCard() {
return (
<div class="card" style="padding: 10px">
<h2>Hello</h2>
<p>Welcome</p>
<img src="logo.png">
<button onclick="alert('hi')">Click me</button>
<!-- This is a comment -->
</div>
);
}
TypeScript and your editor will flag some of them. Find all five before checking the solution.
</aside>
<aside> 🎉
Celebration
JSX is one of those things that feels strange for about two hours and then becomes completely natural. You now know the rules — the rest is just practice.
</aside>
The HackYourFuture curriculum is licensed under CC BY-NC-SA 4.0 *https://hackyourfuture.net/*

Built with ❤️ by the HackYourFuture community · Thank you, contributors
Found a mistake or have a suggestion? Let us know in the feedback form.