# Introduction to React

Course: [React](https://www.devtutorials.ai/learn/react) · Section: React Fundamentals
Source: https://www.devtutorials.ai/learn/react/react-fundamentals/introduction-to-react

> What React is and why developers use it, its main features, React versus plain JavaScript, Single Page Applications, the Virtual DOM, the React ecosystem, how an app is put together, and how to install Node.js, create a Vite project, read its files and run it.

## React Introduction

React is a **JavaScript library**. A library is a collection of ready-made code that you can use in your own project.

React has one job. It helps you build the **user interface**. The user interface is everything a person sees and clicks on a web page.

### Who Made React?

React was created at Facebook (now Meta). It was released to the public in 2013. Today it is free and open source, and thousands of companies use it.

### Real-World Example

A bookshop website shows a header, a search box, a list of books and a cart. The team builds each part as a component: `Header`, `SearchBox`, `BookList` and `CartBadge`.

When a user adds a book, React updates only the number in `CartBadge`. The rest of the page stays as it is, and the browser never reloads the page.

React is a JavaScript library for building user interfaces out of small, reusable pieces called components.

## Your First React Component

A component is a function that returns what should appear on the screen. A React app starts with two files:

- **The App file** holds your first component, `App`. It describes what the page shows: here, a heading and a paragraph.
- **The main file** is the starting point of the app. It finds the empty box on the page (`<div id="root">`) and tells React to show the `App` component inside it.

You write most of your code in the App file. The main file runs once, when the app starts.

      <h1>Welcome to Book Corner</h1>
      <p>Your friendly little bookshop.</p>
    </div>
  );
}
`,
    "main.tsx": `import { createRoot } from "react-dom/client";

// Find the empty <div id="root"> and show App inside it.
createRoot(document.getElementById("root")!).render(<App />);
`,
  }}
/>

The main file shows `App` inside the page, so the heading and the paragraph appear in the preview on the right.

The code inside `return ( ... )` looks like HTML. It is called **JSX**. JSX lets you describe the page in a shape you already know. You will learn JSX in detail in a later lesson.

Change the text inside the `<h1>` and press ▶ Run. The preview updates with your new text. Press Restore code to go back.

## Why React?

Before React, developers changed web pages by hand, one element at a time. On a big page, this becomes hard to follow. React solves three common problems:

- **Messy code** — You describe how the page should look, and React works out what to change.
- **Repeated code** — You build a piece once, such as a product card, and reuse it everywhere.
- **Slow updates** — React changes only the parts of the page that really changed.

## Features of React

These are the main features you will learn in this course.

- **Components.** Build the page from small, reusable pieces, such as a book card or a menu.
- **TSX.** Write HTML-like code inside TypeScript to describe what the page shows.
- **Props.** Pass data from one component to another.
- **State.** Store data that can change. When it changes, the page updates by itself.
- **Declarative code.** Describe what the page should look like, and React works out the steps.
- **Virtual DOM.** React finds the smallest change and updates only that part of the page.
- **One-way data flow.** Data moves from a parent component down to its children, so it is easy to find where a value came from.
- **Hooks.** Functions such as `useState` that add features to a component.
- **Large community.** Millions of developers use React, so help and ready-made tools are easy to find.

You do not need to learn these features now. Each one has its own lesson later in this course.

## React vs Traditional JavaScript

The best way to see the difference is to build the same thing twice.

The app below has a text box and a **Like** button. Type your name in the box first. Then press Like.

### The Traditional Way

This version uses plain JavaScript. Every time you press Like, it rebuilds the whole box with `innerHTML`.

    <button id="like">Like (\` + likes + \`)</button>
  \`;
  document.getElementById("like")!.addEventListener("click", () => {
    likes = likes + 1;
    draw();
  });
}

draw();
`,
  }}
/>

Type a name, then press Like. The count goes up, but **your name disappears**.

This happens because `innerHTML` throws away the old text box and builds a new, empty one. To keep the name, you would need extra code to save it and put it back.

### The React Way

This version uses React. You describe the page once. React updates only what changed.

      <input placeholder="Type your name" />
      <button onClick={() => setLikes(likes + 1)}>Like ({likes})</button>
    </div>
  );
}
`,
    "main.tsx": `import { createRoot } from "react-dom/client";

createRoot(document.getElementById("root")!).render(<App />);
`,
  }}
/>

Type a name, then press Like. The count goes up, and **your name stays**.

React saw that only the button text changed. So it changed only the button text. The text box was left alone.

`useState` gives a component a value it can remember, such as the number of likes. You will learn `useState` in a later lesson.

### Side by Side

<div className="tscroll">

| | Traditional JavaScript | React |
|---|---|---|
| How you work | You change the page step by step | You describe how the page should look |
| Updates | You decide what to change | React works out what to change |
| Reuse | Copy and paste HTML | Write a component once, use it many times |
| Big apps | Gets hard to follow | Stays organised in small components |

</div>

## Single Page Applications (SPA)

### The Old Way: Many Pages

On a traditional website, each page is a separate file. When you click a link, the browser asks the server for a new page. The screen goes blank for a moment, and the whole page loads again.

### The SPA Way: One Page

A **Single Page Application** loads one page only once. After that, when you click a link, JavaScript swaps the content inside that same page. Nothing reloads.

Gmail, Google Maps and YouTube work this way.

### Try It

Press the buttons below. The content changes, but the page does not reload. The console message "Book Corner loaded" appears only once, which proves the page loaded only once.

      <nav>
        <button onClick={() => setPage("home")}>Home</button>{" "}
        <button onClick={() => setPage("books")}>Books</button>{" "}
        <button onClick={() => setPage("about")}>About</button>
      </nav>

      {page === "home" && <h2>Welcome to Book Corner</h2>}
      {page === "books" && <h2>Our Books</h2>}
      {page === "about" && <h2>About Us</h2>}
    </div>
  );
}
`,
    "main.tsx": `import { createRoot } from "react-dom/client";

createRoot(document.getElementById("root")!).render(<App />);
`,
  }}
/>

React is very good at building SPAs. Real apps use a library called a **router** to do this switching. You will learn routing later in the course.

## Virtual DOM

### What Is the DOM?

The **DOM** (Document Object Model) is how the browser sees your web page. Each part of the page, such as a heading or a button, is stored as an object.

When the DOM changes, the browser updates the screen.

### What Is the Virtual DOM?

The **Virtual DOM** is a copy of the DOM that React keeps. React changes this copy first, because it is fast.

Then React updates only the parts of the real page that changed.

### How It Works

When something changes, React follows three steps:

1. **Render** — React builds a new Virtual DOM with the change.
2. **Compare** — React compares the new Virtual DOM with the old one. This step is called **diffing**.
3. **Update** — React changes only the parts of the Real DOM that are different.

<figure className="react-fig ngc-fig">
<svg viewBox="0 0 560 215" role="img" aria-labelledby="fig-vdom-anim" style={{ width: "100%", maxWidth: 560, height: "auto" }}>
  <title id="fig-vdom-anim">Animation: React builds a new Virtual DOM, compares it with the old one, and updates only the changed button in the Real DOM</title>
  <defs><marker id="vdom-arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto"><path d="M0 0 L10 5 L0 10 z" style={{ fill: "var(--ngc-orange-soft)", stroke: "var(--ngc-orange)", strokeWidth: 1.5 }} /></marker></defs>
  <g style={{ fontFamily: "var(--sans)", fontSize: 13, fontWeight: 700 }}>
    <text x="95" y="22" textAnchor="middle" style={{ fill: "var(--ngc-purple)" }}>Old Virtual DOM</text>
    <text x="280" y="22" textAnchor="middle" style={{ fill: "var(--ngc-blue)" }}>New Virtual DOM</text>
    <text x="465" y="22" textAnchor="middle" style={{ fill: "var(--ngc-green)" }}>Real DOM (page)</text>
  </g>
  <g style={{ fontFamily: "var(--mono)", fontSize: 12 }}>
    <line x1="80" y1="64" x2="53" y2="90" style={{ stroke: "var(--ngc-purple)", strokeWidth: 2 }} /><line x1="110" y1="64" x2="137" y2="90" style={{ stroke: "var(--ngc-purple)", strokeWidth: 2 }} />
    <rect x="45" y="34" width="100" height="30" rx="7" style={{ fill: "var(--ngc-purple-soft)", stroke: "var(--ngc-purple)", strokeWidth: 1.5 }}></rect><text x="95" y="53" textAnchor="middle" style={{ fill: "var(--ngc-purple)", fontWeight: 700 }}>div</text>
    <rect x="7" y="90" width="85" height="30" rx="7" style={{ fill: "var(--ngc-purple-soft)", stroke: "var(--ngc-purple)", strokeWidth: 1.5 }}></rect><text x="50" y="109" textAnchor="middle" style={{ fill: "var(--ngc-purple)", fontWeight: 700 }}>h1 Post</text>
    <rect x="98" y="90" width="85" height="30" rx="7" style={{ fill: "var(--ngc-purple-soft)", stroke: "var(--ngc-purple)", strokeWidth: 1.5 }}></rect><text x="140" y="109" textAnchor="middle" style={{ fill: "var(--ngc-purple)", fontWeight: 700 }}>Likes: 0</text>
  </g>
  <g style={{ fontFamily: "var(--mono)", fontSize: 12 }} opacity="0">
    <animate attributeName="opacity" values="0;1;1;1;0" keyTimes="0;0.1;0.85;0.95;1" dur="8s" repeatCount="indefinite" />
    <line x1="265" y1="64" x2="238" y2="90" style={{ stroke: "var(--ngc-blue)", strokeWidth: 2 }} /><line x1="295" y1="64" x2="322" y2="90" style={{ stroke: "var(--ngc-blue)", strokeWidth: 2 }} />
    <rect x="230" y="34" width="100" height="30" rx="7" style={{ fill: "var(--ngc-blue-soft)", stroke: "var(--ngc-blue)", strokeWidth: 1.5 }}></rect><text x="280" y="53" textAnchor="middle" style={{ fill: "var(--ngc-blue)", fontWeight: 700 }}>div</text>
    <rect x="192" y="90" width="85" height="30" rx="7" style={{ fill: "var(--ngc-blue-soft)", stroke: "var(--ngc-blue)", strokeWidth: 1.5 }}></rect><text x="234" y="109" textAnchor="middle" style={{ fill: "var(--ngc-blue)", fontWeight: 700 }}>h1 Post</text>
    <rect x="283" y="90" width="85" height="30" rx="7" style={{ fill: "var(--ngc-orange-soft)", stroke: "var(--ngc-orange)", strokeWidth: 1.5 }}><animate attributeName="opacity" values="1;1;0.45;1;0.45;1;1" keyTimes="0;0.35;0.42;0.5;0.58;0.65;1" dur="8s" repeatCount="indefinite" /></rect><text x="326" y="109" textAnchor="middle" style={{ fill: "var(--ngc-orange)", fontWeight: 700 }}>Likes: 1</text>
  </g>
  <g opacity="0" style={{ fontFamily: "var(--sans)", fontSize: 12 }}>
    <animate attributeName="opacity" values="0;0;1;1;0" keyTimes="0;0.33;0.38;0.9;1" dur="8s" repeatCount="indefinite" />
    <path d="M 142 124 Q 235 158 326 124" style={{ fill: "none", stroke: "var(--ngc-orange)", strokeWidth: 2, strokeDasharray: "5 4" }} />
    <text x="235" y="158" textAnchor="middle" style={{ fill: "var(--ngc-orange)", fontWeight: 700 }}>different!</text>
  </g>
  <g style={{ fontFamily: "var(--mono)", fontSize: 12 }}>
    <line x1="450" y1="64" x2="423" y2="90" style={{ stroke: "var(--ngc-green)", strokeWidth: 2 }} /><line x1="480" y1="64" x2="507" y2="90" style={{ stroke: "var(--ngc-green)", strokeWidth: 2 }} />
    <rect x="415" y="34" width="100" height="30" rx="7" style={{ fill: "var(--ngc-green-soft)", stroke: "var(--ngc-green)", strokeWidth: 1.5 }}></rect><text x="465" y="53" textAnchor="middle" style={{ fill: "var(--ngc-green)", fontWeight: 700 }}>div</text><rect x="377" y="90" width="85" height="30" rx="7" style={{ fill: "var(--ngc-green-soft)", stroke: "var(--ngc-green)", strokeWidth: 1.5 }}></rect><text x="420" y="109" textAnchor="middle" style={{ fill: "var(--ngc-green)", fontWeight: 700 }}>h1 Post</text>
    <rect x="468" y="90" width="85" height="30" rx="7" style={{ fill: "var(--ngc-green-soft)", stroke: "var(--ngc-green)", strokeWidth: 1.5 }} /><rect x="468" y="90" width="85" height="30" rx="7" opacity="0" style={{ fill: "var(--ngc-orange-soft)", stroke: "var(--ngc-orange)", strokeWidth: 1.5 }}><animate attributeName="opacity" values="0;0;1;1;0" keyTimes="0;0.65;0.68;0.92;1" dur="8s" repeatCount="indefinite" /></rect>
    <text x="510" y="109" textAnchor="middle" style={{ fill: "var(--ngc-green)", fontWeight: 700 }}><animate attributeName="opacity" values="1;1;0;0;1" keyTimes="0;0.65;0.66;0.97;1" dur="8s" repeatCount="indefinite" />Likes: 0</text>
    <text x="510" y="109" textAnchor="middle" opacity="0" style={{ fill: "var(--ngc-orange)", fontWeight: 700 }}><animate attributeName="opacity" values="0;0;1;1;0" keyTimes="0;0.65;0.66;0.97;1" dur="8s" repeatCount="indefinite" />Likes: 1</text>
  </g>
  <g opacity="0" style={{ fontFamily: "var(--sans)", fontSize: 12 }}>
    <animate attributeName="opacity" values="0;0;1;1;0" keyTimes="0;0.6;0.66;0.9;1" dur="8s" repeatCount="indefinite" />
    <path d="M 372 135 Q 440 165 508 124" style={{ fill: "none", stroke: "var(--ngc-orange)", strokeWidth: 2 }} markerEnd="url(#vdom-arrow)" />
    <text x="430" y="168" textAnchor="middle" style={{ fill: "var(--ngc-orange)", fontWeight: 700 }}>only this changes</text>
  </g>
  <rect x="20" y="175" width="520" height="34" rx="17" style={{ fill: "var(--ngc-blue-soft)", stroke: "var(--ngc-blue)", strokeWidth: 1.5 }}><animate attributeName="opacity" values="1;1;0;0" keyTimes="0;0.33;0.34;1" dur="8s" repeatCount="indefinite" /></rect>
  <rect x="20" y="175" width="520" height="34" rx="17" opacity="0" style={{ fill: "var(--ngc-orange-soft)", stroke: "var(--ngc-orange)", strokeWidth: 1.5 }}><animate attributeName="opacity" values="0;0;1;1;0;0" keyTimes="0;0.33;0.34;0.63;0.64;1" dur="8s" repeatCount="indefinite" /></rect>
  <rect x="20" y="175" width="520" height="34" rx="17" opacity="0" style={{ fill: "var(--ngc-green-soft)", stroke: "var(--ngc-green)", strokeWidth: 1.5 }}><animate attributeName="opacity" values="0;0;1;1" keyTimes="0;0.63;0.64;1" dur="8s" repeatCount="indefinite" /></rect>
  <g style={{ fontFamily: "var(--sans)", fontSize: 13, fontWeight: 700 }}>
    <text x="280" y="197" textAnchor="middle" style={{ fill: "var(--ngc-blue)" }} opacity="0"><animate attributeName="opacity" values="0;1;1;0;0" keyTimes="0;0.03;0.31;0.33;1" dur="8s" repeatCount="indefinite" />1. Render: the user clicks Like, React builds a new Virtual DOM</text>
    <text x="280" y="197" textAnchor="middle" style={{ fill: "var(--ngc-orange)" }} opacity="0"><animate attributeName="opacity" values="0;0;1;1;0;0" keyTimes="0;0.33;0.35;0.61;0.63;1" dur="8s" repeatCount="indefinite" />2. Compare (diffing): only the Likes button is different</text>
    <text x="280" y="197" textAnchor="middle" style={{ fill: "var(--ngc-green)" }} opacity="0"><animate attributeName="opacity" values="0;0;1;1;0" keyTimes="0;0.63;0.65;0.97;1" dur="8s" repeatCount="indefinite" />3. Update: React changes only that button on the page</text>
  </g>
</svg>
<figcaption>React builds a new Virtual DOM, compares it with the old one, and updates only what changed.</figcaption>
</figure>

You already saw this in the Like button example. Only the button text was different, so only the button text was updated.

React changes the Virtual DOM first. Then it changes only the parts of the real page that are different.

## Real DOM vs Virtual DOM

<div className="tscroll">

| | Real DOM | Virtual DOM |
|---|---|---|
| What it is | The real page the browser shows | A light copy React keeps in memory |
| Who uses it | The browser | React |
| Speed of a change | Slower, because the screen is redrawn | Fast, because it is only an object in memory |
| On every update | Can be rebuilt by hand, like the `innerHTML` example | Compared first, then only the differences are applied |
| Can you see it? | Yes, it is on the screen | No, it lives only in memory |

</div>

## React Ecosystem Overview

React itself only builds the user interface. The **ecosystem** is the set of tools that work with React. You do not need to learn them now; it helps to know their names.

<div className="tscroll">

| Area | Tool | What it does |
|---|---|---|
| Build tool | Vite | Creates a new project and runs it on your computer (used in this course) |
| Framework | Next.js | Adds pages, routing and server features on top of React |
| Navigation | React Router | Moves between screens without reloading the page |
| Shared data | Redux Toolkit, Zustand | Store data that many components use |
| Styling | Tailwind CSS, CSS Modules | Style components with ready-made classes or separate CSS files |
| Server data | TanStack Query | Loads data from a server and keeps it up to date |
| Testing | React Testing Library | Checks that components work |
| Mobile | React Native | Builds phone apps with the same React ideas |

</div>

## React Application Architecture Overview

A React app is a **tree of components**. One component sits at the top. Other components sit inside it.

For Book Corner, the tree could look like this:

```text
App
├── Header
│   └── NavBar
├── BookList
│   ├── BookCard
│   ├── BookCard
│   └── BookCard
└── Footer
```

### How the Pieces Connect

The app starts from one HTML page with one empty box:

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

Then four steps happen:

1. `index.html` loads `main.tsx`.
2. `main.tsx` finds the empty `root` box.
3. `main.tsx` shows the `App` component inside that box.
4. `App` shows all the other components.

## Installing Node.js

**Node.js** lets JavaScript run outside the browser. React tools need it. It also installs **npm** (Node Package Manager), which downloads libraries such as React.

- Go to **nodejs.org** and download the **LTS** (Long Term Support) version.
- Run the installer and keep the default options.
- Open a new terminal (Command Prompt or PowerShell on Windows, Terminal on Mac).
- Check the install by running these commands:

```bash
node -v
npm -v
```

Each command prints a version number, such as `v22.12.0`. Your number may be different. If you see a version, Node.js is installed.

If the terminal says "not recognized", close it and open a new one.

## Creating a React Application

This course uses **Vite** to create React projects. Vite sets up everything for you.

Open a terminal in the folder where you keep your projects. Then run:

```bash
npm create vite@latest book-corner -- --template react-ts
```

Here is what each part means:

- `npm create vite@latest` — use the newest Vite project creator.
- `book-corner` — the name of your project folder.
- `--template react-ts` — make a React project that uses TypeScript.

If Vite asks you a question, keep the default answer by pressing Enter.

Next, move into the new folder and download the libraries the project needs:

```bash
cd book-corner
npm install
```

`npm install` reads the list of libraries in `package.json` and downloads them into a folder called `node_modules`. It can take a minute.

You may see older guides use `create-react-app`. That tool is no longer recommended. Use Vite for new projects.

## Understanding Project Structure

Open the `book-corner` folder in your code editor. You will see files like these:

```text
book-corner/
├── node_modules/      libraries downloaded by npm install
├── public/            files copied as they are, such as icons
├── src/
│   ├── assets/        images used by your components
│   ├── App.css        styles for the App component
│   ├── App.tsx        the main component
│   ├── index.css      styles for the whole page
│   └── main.tsx       the starting point of the app
├── index.html         the one HTML page
├── package.json       the project's name, scripts and libraries
├── tsconfig.json      TypeScript settings
└── vite.config.ts     Vite settings
```

The exact list can change a little between Vite versions. The important files are always there.

### The Files You Will Edit Most

- **`src/App.tsx`** — your main component. You will spend most of your time here.
- **`src/main.tsx`** — starts React and shows `App` inside the `root` box.
- **`index.html`** — the single page. It holds the empty `root` box.

### The Files You Will Rarely Touch

- **`package.json`** — lists libraries and commands.
- **`tsconfig.json`** and **`vite.config.ts`** — settings files.
- **`node_modules`** — never edit this folder. npm manages it.

The lab below has the same main files as a new Vite project. Click each tab to see how they connect.

);
`,
    "App.tsx": `import "./App.css";

  return (
    <main className="app">
      <h1>Book Corner</h1>
      <p>Edit App.tsx and press Run to see your change.</p>
    </main>
  );
}
`,
    "App.css": `.app {
  text-align: center;
  padding: 16px;
}
`,
    "index.css": `body {
  background: #f8fafc;
}
`,
  }}
/>

`StrictMode` is a helper that warns you about common problems while you develop. It does not change what users see.

## Running a React Application

Inside the `book-corner` folder, run:

```bash
npm run dev
```

This starts a **development server**. It is a small web server that runs on your own computer. The terminal shows something like this:

```text
  VITE ready in 350 ms

  ➜  Local:   http://localhost:5173/
```

Open `http://localhost:5173/` in your browser. You will see the starter React page.

### Live Updates

Keep the server running. Open `src/App.tsx`, change some text and save the file. The browser updates on its own, without a refresh.

This is called **Hot Module Replacement**, or HMR.

### Stopping the Server

Click inside the terminal and press **Ctrl + C**. The server stops, and the page stops working until you run `npm run dev` again.

Easy Way to Remember: **install** once (`npm install`), **dev** every day (`npm run dev`), **Ctrl + C** to stop.

## Common mistakes

<div className="tscroll">

| Mistake | What you see | Fix |
|---|---|---|
| Running `npm run dev` before `npm install` | An error such as `vite: not found` or `'vite' is not recognized` | Run `npm install` first, then `npm run dev` |
| Running commands outside the project folder | An error that mentions `package.json` | Run `cd book-corner` first |
| Starting a component name with a small letter, such as `<bookCard />` | The component shows nothing | Start the name with a capital letter: `<BookCard />` |
| Closing the terminal while the app is running | The page stops loading in the browser | Run `npm run dev` again |
| Using a terminal that was open before Node.js was installed | `node` is not recognized | Close the terminal and open a new one |
| Editing files inside `node_modules` | Your changes disappear after the next `npm install` | Edit only the files inside `src/` |

</div>

## Check Yourself

## Exercises

## What to Remember

- React is a JavaScript library for building user interfaces from small, reusable components.
- React updates only what changed, using the Virtual DOM to find the differences.
- To start a project: `npm create vite@latest`, then `npm install`, then `npm run dev`.

Next: TSX Fundamentals
