Web Development with React
Hands-onBeginner 35 min· React core · 5 of 21

Components and JSX

Build the Brew & Bean page from small components and learn the rules of JSX: one parent, className, braces for JavaScript, and imports and exports between files.

In this lesson you will build the first real screen of the Brew & Bean website from small pieces called components, and learn the rules of JSX, the syntax React uses to describe the screen.

Prerequisites: the brew-and-bean project from *Start a React project with Vite*, running with npm run dev, and the JavaScript from *Modern JavaScript for React* (functions, template strings, ES modules).

What a component is

A component is a JavaScript function that returns a piece of the user interface. Think of LEGO bricks: a header brick, a menu card brick, a footer brick. You snap them together to build a page, and you can reuse a brick as many times as you like.

Two rules make a function a component:

1. Its name starts with a capital letter (Header, not header). React uses the capital letter to tell your components apart from ordinary HTML tags like <header>. 2. It returns something React can draw, usually JSX.

jsx
function Greeting() {
  return <p>Welcome to Brew &amp; Bean</p>;
}

A complete component. Use it like a tag: <Greeting />.

JSX in five rules

JSX looks like HTML but it is JavaScript. A tool in Vite converts it into plain JavaScript calls before the browser sees it. Because it is not exactly HTML, a few rules differ.

How JSX differs from HTML

RuleHTMLJSX
One parent elementSeveral top-level tags allowedReturn one parent: a <div> or an empty fragment <>...</>
Close every tag<br>, <img src="a.png"><br />, <img src="a.png" />
class becomes className<div class="card"><div className="card">
Attributes are camelCaseonclick, tabindexonClick, tabIndex
JavaScript goes in bracesNot possible<p>{price}</p> or <p>{2 + 3}</p>

class is a reserved word in JavaScript, which is why JSX uses className. The htmlFor attribute replaces for on labels for the same reason.

Inside curly braces you can put any JavaScript expression: a variable, a calculation, a function call, a template string, a ternary. You cannot put statements such as if or for there.

jsx
const shop = "Brew & Bean";
const price = 180;

const card = (
  <div className="card">
    <h3>{shop} Cappuccino</h3>
    <p>Price: ₹{price}</p>
    <p>With GST (5%): ₹{price * 1.05}</p>
  </div>
);

Braces drop a JavaScript value into the markup. Text inside JSX that is not in braces is plain text. Tax here is only for illustration.

Double braces

Styles in JSX take an object, not a string: style={{ color: "red", fontSize: 18 }}. The double braces are one pair for "JavaScript here" and one pair for the object. For most styling, use a className and a CSS file instead.

Build the page

We will make three components, each in its own file inside src/, and put them together in App. A common convention is one component per file, named after the component, with a default export.

What to do

  1. 1In VS Code create src/Header.jsx, src/MenuCard.jsx and src/Footer.jsx.
  2. 2Paste the code from the three blocks below into the matching files.
  3. 3Replace src/App.jsx with the version below.
  4. 4Replace src/index.css with the CSS below.
  5. 5Run npm run dev if it is not running, and look at the browser.
src/Header.jsx
export default function Header() {
  return (
    <header className="header">
      <h1>Brew &amp; Bean</h1>
      <p>Indiranagar, Bengaluru. Open 8 am to 10 pm. Pickup only.</p>
    </header>
  );
}

A header with the shop name. The &amp; is how you write an ampersand in JSX text.

src/MenuCard.jsx
export default function MenuCard() {
  return (
    <article className="card">
      <h3>Espresso</h3>
      <p className="category">coffee</p>
      <p className="price">₹120</p>
    </article>
  );
}

One menu card with the content typed in directly. This is deliberately limited; the next lesson fixes it.

src/Footer.jsx
export default function Footer() {
  const year = new Date().getFullYear();

  return (
    <footer className="footer">
      <p>&copy; {year} Brew &amp; Bean, Indiranagar</p>
    </footer>
  );
}

Shows JavaScript running before the return: we compute the year, then use it with braces.

src/App.jsx
import Header from "./Header.jsx";
import MenuCard from "./MenuCard.jsx";
import Footer from "./Footer.jsx";

export default function App() {
  return (
    <>
      <Header />
      <main className="page">
        <h2>Today's menu</h2>
        <div className="menu-grid">
          <MenuCard />
          <MenuCard />
          <MenuCard />
        </div>
      </main>
      <Footer />
    </>
  );
}

App imports the other components and uses them as tags. The empty tags <> and </> are a fragment: a parent that adds nothing to the page.

src/index.css
body {
  margin: 0;
  font-family: system-ui, sans-serif;
  background: #fffaf3;
  color: #2b1d14;
}

.header {
  padding: 24px;
  background: #4a2c1a;
  color: #fff;
}

.header h1,
.header p {
  margin: 0;
}

.page {
  max-width: 900px;
  margin: 0 auto;
  padding: 24px;
}

.menu-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 16px;
}

.card {
  padding: 16px;
  background: #fff;
  border: 1px solid #e6d5c3;
  border-radius: 12px;
}

.card h3 {
  margin: 0 0 8px;
}

.category {
  margin: 0;
  color: #8a6a50;
  text-transform: capitalize;
}

.price {
  margin: 8px 0 0;
  font-weight: 700;
}

.footer {
  padding: 16px;
  text-align: center;
  color: #8a6a50;
}
Output
A brown header with "Brew & Bean", the heading "Today's menu", three identical white cards saying Espresso, coffee, ₹120 in a responsive grid, and a footer with the current year.

Notice what you did: you wrote <MenuCard /> three times and got three cards. That is reuse. The problem is also clear: all three show Espresso. You need a way to give each card different data, and that is props, the next lesson.

How React sees your page

Your components form a tree: App is the root, Header, main and Footer are its children, and each MenuCard is a child of the grid. When data changes, React re-runs the affected component functions, compares the new result with the old one, and updates only the parts of the real page that changed. You describe what the screen should look like; React works out how to get there.

Common mistakes

Errors you will certainly see

MistakeWhat happensFix
Lowercase component name (<menuCard />)React treats it as an HTML tag and shows nothing usefulCapitalise: <MenuCard />
Two sibling elements at the top of a returnError: adjacent JSX elements must be wrappedWrap in a <div> or a fragment <>...</>
class="card"A warning in the console, and styling may not applyUse className
Unclosed tag (<img src="x.png">)Syntax error overlaySelf-close: <img src="x.png" />
Forgetting export defaultError: does not provide an export named defaultAdd it, and import with the same file name
Writing return on one line and the JSX on the nextThe function returns undefinedPut ( after return and the JSX inside parentheses

Debugging JSX

Read the overlay in the browser and the console in DevTools (F12). Errors name the file and line. In JSX, nearly every beginner error is a missing closing tag, a missing parent element or a capital letter.

Prompt · Convert HTML to JSX
Convert this HTML into a React component written in JSX (plain JavaScript). Keep the structure, change attributes to the JSX versions (className, htmlFor, camelCase events), self-close void tags, and wrap in a single parent or fragment. Name the component [ComponentName].

---
[paste your HTML]
---

Then list every change you made so I can learn the rules.

What to expect: Check class became className, void tags are self-closed, and the list of changes matches what the code actually does.

Try it: Add a Specials component

Create src/Special.jsx that shows a box with the text "Today's special: Filter Coffee, ₹80" (use the real price from the menu). Use it in App between the heading and the grid. Give it a className and style it in index.css.

Key takeaways

  1. A component is a function with a capitalised name that returns JSX; you use it as a tag.
  2. JSX is not HTML: one parent element, self-closed tags, className, camelCase attributes, JavaScript in { }.
  3. One component per file, export default, then import it where it is used.
  4. Components nest into a tree, and you can reuse the same component many times.
  5. Hard-coded content limits reuse; props, next, let each copy show different data.

Check yourself

Finishing the quiz marks the lesson as done.

1. Why does a React component's name have to start with a capital letter?

2. Which JSX is correct?

3. What can go inside curly braces in JSX?

4. Your component returns two sibling elements, <h1> and <p>, and React reports an error. What is the simplest fix?

5. You render <MenuCard /> three times and see three identical cards. What is missing?

Saved on this device. Create a free account to keep it on every device.

Practise this with Sam

A real mock interview, out loud, with an honest scorecard. Free to start.

Start free