Margherita
Tomato, mozzarella, basil
Price: 8.50 €
Nikita Goluban
Full-Stack Developer Logistics & Marketing Mechanical & Construction Skills Woodwork & Metalwork Polyglot
React.js + Next.js · Module 2. React Basics · Lesson 9
Before Pizza Palace can appear in a browser, React needs to know two things:
In a typical React project created with Vite, this process begins in main.tsx. React uses createRoot() and render() to connect the component tree to the browser's DOM.
index.html and main.tsx do.document.getElementById() finds the root container.createRoot() and .render() do.StrictMode does.REACT · 01
DOM means Document Object Model. It is the browser's object representation of an HTML document.
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Pizza Palace</title>
</head>
<body>
<h1>Pizza Palace</h1>
<p>Fresh pizza delivered to your door.</p>
</body>
</html>
The browser represents this document as a tree:
document
└── html
├── head
│ └── title
└── body
├── h1
└── p
JavaScript can access DOM elements with methods such as:
document.getElementById("root");
document.querySelector("h1");
React ultimately uses the browser DOM to display its user interface.
REACT · 02
A React application needs an existing HTML element that acts as its container. In a Vite project, it is normally:
<div id="root"></div>
The element exists before React starts. It is empty at first, so it has no visible browser result by itself. React places the Pizza Palace interface inside it.
Before React After React renders
div#root div#root
└── App
├── Header
├── Menu
└── CartSummary
React manages the root container's content; it does not replace the complete HTML document.
REACT · 03
In a typical Vite project, index.html is located in the project root.
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0"
/>
<title>Pizza Palace</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
<div id="root"></div> provides the DOM container.<script type="module" src="/src/main.tsx"></script> identifies the application entry point.main.tsx and serves browser-compatible modules.We do not manually write the whole pizza menu in index.html. React components describe that interface with JSX.
The final result depends on the component rendered by main.tsx. With the App component from Topic 8, the browser will show the Pizza Palace heading and welcome message.
REACT · 04
main.tsx is the entry point of a typical React and TypeScript application.
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import "./index.css";
import App from "./App.tsx";
createRoot(document.getElementById("root")!).render(
<StrictMode>
<App />
</StrictMode>
);
Read the last expression from the inside out:
id="root".App component inside StrictMode.The import statements and startup call do not define the visible design. App and its child components do that.
REACT · 05
import { StrictMode } from "react";
This imports React's development-checking wrapper.
import { createRoot } from "react-dom/client";
This imports the function that creates a React root in the browser.
import "./index.css";
This asks Vite to include the global stylesheet.
import App from "./App.tsx";
This imports the root component. These import statements prepare dependencies and do not produce visible browser content on their own.
REACT · 06
document.getElementById("root") is a standard DOM method. It looks for this element:
<div id="root"></div>
const container = document.getElementById("root");
console.log(container);
<div id="root"></div>
If the ID cannot be found, the method returns null.
document.getElementById("root")!
The ! is TypeScript's non-null assertion operator. It tells TypeScript that we expect the value not to be null. It does not create the element and does not check it at runtime.
A safer startup pattern performs a real check:
const container = document.getElementById("root");
if (!container) {
throw new Error("Root element not found");
}
createRoot(container).render(<App />);
This produces a clear error when index.html and main.tsx do not agree.
REACT · 07
createRoot() creates a React root associated with a DOM container.
const container = document.getElementById("root");
if (!container) {
throw new Error("Root element not found");
}
const root = createRoot(container);
At this point:
container is the real HTML element;root lets React manage content inside that element;Creating a root does not automatically display Pizza Palace. We still need root.render(...).
REACT · 08
The .render() method tells React which component should appear inside the root.
export default function App() {
return (
<main>
<h1>Pizza Palace</h1>
<p>Choose your favourite pizza and order online.</p>
</main>
);
}
import { createRoot } from "react-dom/client";
import App from "./App.tsx";
const container = document.getElementById("root");
if (!container) {
throw new Error("Root element not found");
}
const root = createRoot(container);
root.render(<App />);
React processes <App /> and places the resulting DOM inside #root.
main.tsx mounts App inside the root container.REACT · 09
The root component is at the top of the application's component tree. Vite projects conventionally call it App, but the name is not mandatory.
function Header() {
return <h1>Pizza Palace</h1>;
}
function FeaturedPizza() {
return <p>Featured: Margherita — 8.50 €</p>;
}
export default function App() {
return (
<main>
<Header />
<FeaturedPizza />
</main>
);
}
App
├── Header
└── FeaturedPizza
App, then renders its two child components.If the component were called PizzaShop, the startup code could use root.render(<PizzaShop />) instead.
REACT · 10
StrictMode enables additional development checks for the components inside it.
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import App from "./App.tsx";
const container = document.getElementById("root");
if (!container) {
throw new Error("Root element not found");
}
createRoot(container).render(
<StrictMode>
<App />
</StrictMode>
);
It can help detect:
In development, React can call rendering functions an extra time to expose accidental side effects:
export default function App() {
console.log("Pizza Palace rendered");
return <h1>Pizza Palace</h1>;
}
Extra development calls do not mean duplicate visible DOM elements were created. Strict Mode's extra checks do not run in the production build.
REACT · 11
A real pizza-ordering application is divided into focused components.
src/
├── components/
│ ├── Header.tsx
│ ├── FeaturedPizza.tsx
│ └── Footer.tsx
├── App.tsx
└── main.tsx
export default function Header() {
return <header><h1>Pizza Palace</h1></header>;
}
export default function FeaturedPizza() {
return (
<article>
<h2>Margherita</h2>
<p>Tomato, mozzarella, basil</p>
<p>Price: 8.50 €</p>
</article>
);
}
export default function Footer() {
return <footer><p>Pizza Palace — Fresh every day</p></footer>;
}
import Header from "./components/Header";
import FeaturedPizza from "./components/FeaturedPizza";
import Footer from "./components/Footer";
export default function App() {
return (
<div>
<Header />
<main><FeaturedPizza /></main>
<Footer />
</div>
);
}
main.tsx renders App; App renders the header, featured pizza, and footer.REACT · 12
The initial render happens when React first displays the application:
root.render(<App />);
A re-render happens when React calculates a component's output again, commonly after its state or props change.
import { useState } from "react";
export default function App() {
const [quantity, setQuantity] = useState(1);
function addPizza() {
setQuantity(quantity + 1);
}
return (
<main>
<h1>Your Cart</h1>
<p>Margherita quantity: {quantity}</p>
<button onClick={addPizza}>Add one</button>
</main>
);
}
React re-runs App, compares the new result with the previous one, and updates the necessary DOM content.
REACT · 13
React keeps an internal representation of the interface. This idea is commonly explained with the term Virtual DOM.
JSX
↓
React elements
↓
Render calculation
↓
Comparison with the previous result
↓
Necessary browser DOM updates
Suppose the old output is:
<p>Total: 8.50 €</p>
After a cart update, it becomes:
<p>Total: 17.00 €</p>
The visible result changes from Total: 8.50 € to Total: 17.00 €. React can update that text without rebuilding or reloading the entire page.
Re-rendering means React recalculates component output. It does not mean every DOM node is necessarily replaced.
REACT · 14
Most applications create one root and call .render() once during startup:
createRoot(document.getElementById("root")!).render(
<App />
);
After startup, events update state:
setQuantity(quantity + 1);
React handles the resulting re-render. We do not normally call root.render() whenever the customer adds a pizza.
React supports multiple roots when React must manage separate areas of an existing page, but a beginner Vite application normally needs only one.
REACT · 15
Pizza Palace can use this component structure:
src/
├── components/
│ ├── Header.tsx
│ ├── Navigation.tsx
│ ├── PizzaMenu.tsx
│ ├── CartSummary.tsx
│ └── Footer.tsx
├── App.tsx
└── main.tsx
function Header() {
return <header><h1>Pizza Palace</h1></header>;
}
function Navigation() {
return <nav>Menu · Offers · Your cart</nav>;
}
function PizzaMenu() {
return (
<section>
<h2>Popular pizzas</h2>
<article><h3>Margherita</h3><p>8.50 €</p></article>
<article><h3>Pepperoni</h3><p>10.50 €</p></article>
</section>
);
}
function CartSummary() {
return <aside><h2>Your cart</h2><p>0 items</p></aside>;
}
function Footer() {
return <footer><p>Order online for delivery or pickup.</p></footer>;
}
export default function App() {
return (
<div>
<Header />
<Navigation />
<main>
<PizzaMenu />
<CartSummary />
</main>
<Footer />
</div>
);
}
main.tsx starts the React application. App.tsx defines its main structure, while every child component owns one part of the interface.
REACT · 16
If index.html does not contain <div id="root"></div>, document.getElementById("root") returns null and React has no container.
These values must match:
<div id="app"></div>
document.getElementById("root"); // Returns null
Use the same ID in both files.
If App.tsx is inside src/components, this path is incorrect:
import App from "./App";
The matching relative path is:
import App from "./components/App";
Creating const root = createRoot(container) is not enough. Call root.render(<App />) to display the application.
Avoid root.render(App()). Use root.render(<App />) so React treats App as a component and manages it correctly.
Do not use document.querySelector() to perform ordinary updates inside the React root. Express changing interface data with state and props.
Extra development render calls are intentional checks. They do not necessarily indicate an application bug or create duplicate visible content.
REACT · 17
Create <div id="root"></div> and explain what document.getElementById("root") returns.
Complete the missing value:
const root = createRoot(container);
root.render(________);
Expected answer:
<App />
Create Header, PizzaMenu, and Footer. Render all three inside App and draw the resulting component tree.
Wrap <App /> in <StrictMode>. Log a message inside App and compare the visible page with the development console.
Create a pizza quantity with useState. Add a button that increments it and observe how the text changes without a full reload.
Replace the non-null assertion with an if (!container) check and a clear error message.
REACT · 18
<div id="root"></div> in index.html.main.tsx is the browser application's entry point.document.getElementById("root") finds the container and can return null.createRoot() connects React to the container..render(<App />) starts rendering the component tree.App is a conventional root-component name, not a requirement.StrictMode adds development checks without changing the production interface..render() once and use state for later updates.Next lesson: Styling Pizza Palace components with inline styles, regular CSS, and locally scoped CSS Modules.