← Back

React.js + Next.js · Module 2. React Basics · Lesson 9

Rendering a React Application in the DOM

Before Pizza Palace can appear in a browser, React needs to know two things:

  1. Where the application should be displayed in the HTML document.
  2. Which component should be rendered first.

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.

You will learn

  1. What the DOM is.
  2. How React connects to an HTML document.
  3. What index.html and main.tsx do.
  4. How document.getElementById() finds the root container.
  5. What createRoot() and .render() do.
  6. What the root component is.
  7. What StrictMode does.
  8. How React renders nested components.
  9. The difference between the initial render and a re-render.
  10. How React updates only the necessary DOM content.
  11. Common application-startup mistakes.

REACT · 01

1. What Is the DOM?

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

Browser Result

Pizza Palace

Fresh pizza delivered to your door.

The browser turns the HTML into visible DOM elements.

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

2. How React Connects to HTML

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

3. Understanding index.html

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>

What the Important Lines Do

  • <div id="root"></div> provides the DOM container.
  • <script type="module" src="/src/main.tsx"></script> identifies the application entry point.
  • Vite processes the TypeScript and JSX imported from 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.

Browser Result

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

4. Understanding main.tsx

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:

  1. Find the element with id="root".
  2. Create a React root connected to that element.
  3. Render the 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

5. Importing React Features

StrictMode

import { StrictMode } from "react";

This imports React's development-checking wrapper.

createRoot

import { createRoot } from "react-dom/client";

This imports the function that creates a React root in the browser.

Global CSS

import "./index.css";

This asks Vite to include the global stylesheet.

App Component

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

6. Understanding document.getElementById()

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);

Console Result

<div id="root"></div>

If the ID cannot be found, the method returns null.

What Does the Exclamation Mark Mean?

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

7. What Does createRoot() Do?

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;
  • nothing has been rendered yet.

Creating a root does not automatically display Pizza Palace. We still need root.render(...).


REACT · 08

8. What Does render() Do?

The .render() method tells React which component should appear inside the root.

App.tsx

export default function App() {
  return (
    <main>
      <h1>Pizza Palace</h1>
      <p>Choose your favourite pizza and order online.</p>
    </main>
  );
}

main.tsx

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.

Browser Result

Pizza Palace

Choose your favourite pizza and order online.

main.tsx mounts App inside the root container.

REACT · 09

9. The Root Component — App

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>
  );
}

Component Tree

App
├── Header
└── FeaturedPizza

Browser Result

Pizza Palace

Featured: Margherita — 8.50 €

React begins with App, then renders its two child components.

If the component were called PizzaShop, the startup code could use root.render(<PizzaShop />) instead.


REACT · 10

10. Understanding React.StrictMode

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:

  • impure rendering logic;
  • effects that do not clean up correctly;
  • deprecated API usage;
  • problems with certain ref callbacks.

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>;
}

Browser and Console Result

Pizza Palace

The heading appears once. The development console may log the render more than once because of Strict Mode checks.

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

11. Rendering Nested Components

A real pizza-ordering application is divided into focused components.

src/
├── components/
│   ├── Header.tsx
│   ├── FeaturedPizza.tsx
│   └── Footer.tsx
├── App.tsx
└── main.tsx

Header.tsx

export default function Header() {
  return <header><h1>Pizza Palace</h1></header>;
}

FeaturedPizza.tsx

export default function FeaturedPizza() {
  return (
    <article>
      <h2>Margherita</h2>
      <p>Tomato, mozzarella, basil</p>
      <p>Price: 8.50 €</p>
    </article>
  );
}

Footer.tsx

export default function Footer() {
  return <footer><p>Pizza Palace — Fresh every day</p></footer>;
}

App.tsx

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>
  );
}

Browser Result

Pizza Palace

Margherita

Tomato, mozzarella, basil

Price: 8.50 €

Pizza Palace — Fresh every day

main.tsx renders App; App renders the header, featured pizza, and footer.

REACT · 12

12. Rendering vs Re-Rendering

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>
  );
}

Browser Result

Your Cart

Before click

Margherita quantity: 1

After click

Margherita quantity: 2

Clicking updates the quantity without reloading the webpage.

React re-runs App, compares the new result with the previous one, and updates the necessary DOM content.


REACT · 13

13. React Rendering and DOM Updates

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

14. Does React Need Multiple render() Calls?

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

15. Practical Application — Pizza Palace

Pizza Palace can use this component structure:

src/
├── components/
│   ├── Header.tsx
│   ├── Navigation.tsx
│   ├── PizzaMenu.tsx
│   ├── CartSummary.tsx
│   └── Footer.tsx
├── App.tsx
└── main.tsx

App.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.

Browser Result

Pizza Palace

Menu · Offers · Your cart

Popular pizzas

Margherita

8.50 €

Pepperoni

10.50 €

Your cart

0 items

Order online for delivery or pickup.

The root component combines the main sections of the online pizza shop.

REACT · 16

16. Common Beginner Mistakes

Mistake 1 — Missing Root Element

If index.html does not contain <div id="root"></div>, document.getElementById("root") returns null and React has no container.

Mistake 2 — Different IDs

These values must match:

<div id="app"></div>
document.getElementById("root"); // Returns null

Use the same ID in both files.

Mistake 3 — Incorrect Import Path

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";

Mistake 4 — Forgetting render()

Creating const root = createRoot(container) is not enough. Call root.render(<App />) to display the application.

Mistake 5 — Calling App as a Normal Function

Avoid root.render(App()). Use root.render(<App />) so React treats App as a component and manages it correctly.

Mistake 6 — Manually Updating React-Controlled DOM

Do not use document.querySelector() to perform ordinary updates inside the React root. Express changing interface data with state and props.

Mistake 7 — Misunderstanding Strict Mode

Extra development render calls are intentional checks. They do not necessarily indicate an application bug or create duplicate visible content.


REACT · 17

17. Practice Exercises

Exercise 1 — Find the Root Element

Create <div id="root"></div> and explain what document.getElementById("root") returns.

Exercise 2 — Render App

Complete the missing value:

const root = createRoot(container);
root.render(________);

Expected answer:

<App />

Exercise 3 — Pizza Component Tree

Create Header, PizzaMenu, and Footer. Render all three inside App and draw the resulting component tree.

Exercise 4 — StrictMode

Wrap <App /> in <StrictMode>. Log a message inside App and compare the visible page with the development console.

Exercise 5 — Cart State Update

Create a pizza quantity with useState. Add a button that increments it and observe how the text changes without a full reload.

Exercise 6 — Safe Root Check

Replace the non-null assertion with an if (!container) check and a clear error message.


REACT · 18

18. Key Takeaways

  • React needs an existing DOM container.
  • Vite projects normally provide <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.
  • Nested components form a tree beginning with the root component.
  • State and prop changes can cause re-renders without a full page reload.
  • Re-rendering recalculates component output; React then applies the necessary DOM updates.
  • Most applications call .render() once and use state for later updates.

Further Reading

Next lesson: Styling Pizza Palace components with inline styles, regular CSS, and locally scoped CSS Modules.

← Back↑ Back to the top