COMPLETE REACT COURSE  •  PART 5 of 5

Advanced & Professional React

Patterns used by component libraries, TypeScript, automated testing, and ten capstone projects you can deploy and show in your portfolio.

4modules
40practice examples
~21hclass time
100%live code
Keys: → next   ← back   M menu   L Code Lab   F fullscreen
M17
Advanced Patterns & React 19
Portals, error boundaries, compound components
M18
TypeScript with React
Typed props, state, events, generics
M19
Testing React Apps
Vitest, Testing Library, mocks, TDD
M20
Capstone Projects & Deployment
10 projects, deploy, portfolio, certificate
BrainBit Infotech, Ranchi  |  Trainer: Nandan Kumar
17
MODULE 17  •  PART 5

Advanced Patterns & React 19

Patterns used inside professional component libraries: portals for modals, error boundaries that stop crashes, compound components, and a look at what React 19 and Server Components add.

  • Portals: render outside the parent box
  • Error boundaries: crash protection
  • Compound components
  • Render props & HOCs (reading old code)
  • useId and other handy hooks
  • React 19: Actions, useOptimistic, use()
  • Server Components & Next.js (overview)
  • Accessible, reusable components
YOU WILL BUILD:Portal modalError boundaryTooltipCompound accordionToast systemOptimistic like button
🎪
App.jsx
return createPortal(
  <div className="modal">
    {children}
  </div>,
  document.body
);
10examples
● 5 Easy
● 3 Medium
● 2 Hard
each with live code
Complete React Course  |  BrainBit Infotech, Ranchi
M17Real-world use

Where is this used in real apps?

dashboard.myapp.in
Sales widget
Rs 4.2 L
⚠️ Weather widget failed to load.
Try again (error boundary)
Tabs: Fees | Results | Attendance (compound)
❤️ 129 (optimistic: counts instantly)
🪟 Modal (rendered with a portal, above everything)

Modals & tooltips

They must float above everything, even when created deep inside a small card. Portals make that possible.

One broken widget, not a broken app

Error boundaries show a fallback for the failed part while the rest of the dashboard keeps working.

Library-style APIs

<Tabs><Tabs.Tab /><Tabs.Panel /></Tabs>: flexible components used by MUI, Radix, Headless UI and shadcn/ui.
Complete React Course  |  Part 5  |  Advanced Patterns & React 19
M17Animated explainer

Portals: render outside the parent

❌ Modal inside a small card

Course card (overflow: hidden)
Modal: Enroll now?
(bottom half is CUT OFF)
The modal is a child of the card in the DOM, so the card's overflow:hidden and z-index clip it.

✅ With createPortal

App.jsx
import { createPortal } from 'react-dom';

function Modal({ children }) {
  return createPortal(
    <div className="backdrop">
      <div className="modal">{children}</div>
    </div>,
    document.body      // render HERE instead
  );
}
Best of bothIn the DOM the modal lives at the end of <body> (not clipped). In React it is still a child: it gets props, context and events from its parent.
Complete React Course  |  Part 5  |  Advanced Patterns & React 19
M17Animated explainer

Error boundaries: stop one crash from killing the app

Without an error boundary

app
Sales
Weather
Notices
Calendar

With an error boundary around each widget

app
Sales ✅
⚠️ Weather failed. Retry
Notices ✅
Calendar ✅
App.jsx
<ErrorBoundary fallback={<p>Weather failed. Retry</p>}>
  <WeatherWidget />
</ErrorBoundary>
Complete React Course  |  Part 5  |  Advanced Patterns & React 19
M17Recognise them

Patterns you will meet in real codebases

🧩 Compound components

Parent shares state with its parts through context. Flexible and readable.
App.jsx
<Tabs defaultTab="fees">
  <Tabs.List>
    <Tabs.Tab id="fees">Fees</Tabs.Tab>
    <Tabs.Tab id="marks">Marks</Tabs.Tab>
  </Tabs.List>
  <Tabs.Panel id="fees">...</Tabs.Panel>
</Tabs>

🎨 Render props

Pass a FUNCTION that returns JSX, so the parent controls how each item looks.
App.jsx
<DataList
  items={students}
  renderItem={(s) => (
    <b>{s.name}</b>
  )}
/>

🎁 Higher-Order Components

A function that takes a component and returns an enhanced one. Common in older code; hooks replaced most uses.
App.jsx
const SecurePage = withAuth(Dashboard);

function withAuth(Comp) {
  return (props) => isLoggedIn()
    ? <Comp {...props} />
    : <Login />;
}
Handy hookUse it for
useId()Unique ids for label/input pairs and ARIA attributes (safe with server rendering)
useLayoutEffectMeasure the DOM before the browser paints (tooltips positioning)
useImperativeHandleExpose custom methods (like open()) from a component via ref
useSyncExternalStoreSubscribe to external data sources (used inside state libraries)
Complete React Course  |  Part 5  |  Advanced Patterns & React 19
M17What is new

React 19 highlights

React 19: useActionState
// Actions: a form can call an async function directly
function SubscribeForm() {
  const [state, formAction, isPending] = useActionState(
    async (prev, formData) => {
      await saveEmail(formData.get('email'));
      return { ok: true };
    },
    { ok: false }
  );
  return (
    <form action={formAction}>
      <input name="email" />
      <button disabled={isPending}>Subscribe</button>
      {state.ok && <p>Thanks!</p>}
    </form>
  );
}
more React 19
// Show the result before the server confirms
const [optimisticLikes, addLike] = useOptimistic(
  likes, (cur, n) => cur + n);

// Read a promise or context with use()
const user = use(userPromise);   // suspends until ready

// ref is a normal prop, <title> works anywhere
function Input({ ref }) { return <input ref={ref} />; }
<title>Cart (3) | MyShop</title>
In real projectsOur live previews run React 18, so Example 10 builds the optimistic pattern by hand. The ideas are identical; React 19 just gives you built-in hooks.
Complete React Course  |  Part 5  |  Advanced Patterns & React 19
M17Big picture

Server Components & Next.js (overview)

🖥️ Server Component (default in Next.js)runs on the server: reads the database directly, sends finished HTML, ZERO JavaScript to the browser
↓ HTML + small data
💻 Client Component ('use client')runs in the browser: useState, onClick, effects (everything you learned)
App.jsx
// app/courses/page.jsx  (Server Component)
export default async function CoursesPage() {
  const courses = await db.course.findMany();  // on the server!
  return courses.map((c) => <CourseCard key={c.id} course={c} />);
}

// components/EnrollButton.jsx
'use client';
export default function EnrollButton() {
  const [done, setDone] = useState(false);
  return <button onClick={() => setDone(true)}>{done ? 'Enrolled' : 'Enroll'}</button>;
}
Plain React + Vite (this course)Next.js (React framework)
Single Page App, runs in the browserServer + client rendering, file-based routing
Great for dashboards, admin panels, internal toolsGreat for SEO-heavy sites: shops, blogs, marketing
You add Router, data fetching yourselfRouting, data loading, image optimisation built in
Complete React Course  |  Part 5  |  Advanced Patterns & React 19
M17Practice 1 of 10  •  Easy

Example 1: Modal with createPortal

● Easy💼 Real project: Confirm dialogs, login popups
The modal is rendered into document.body with a portal, so the card's overflow: hidden cannot clip it. Clicking the dark backdrop or pressing the button closes it.
App.jsxModal.jsx
LIVELive Preview
Console
✍ Try it yourself Close the modal when the user presses Escape (add a keydown listener in an effect inside Modal).
useEffect with window.addEventListener('keydown', e => e.key === 'Escape' && onClose()) and a cleanup.
Complete React Course  |  Part 5  |  Advanced Patterns & React 19
M17Practice 2 of 10  •  Easy

Example 2: Error Boundary Protects a Widget

● Easy💼 Real project: Dashboards with many independent widgets
The ErrorBoundary class component catches errors thrown while its children render. Click "Break the weather widget": only that box shows a fallback, the rest keeps working. The console shows React reporting the error.
App.jsxErrorBoundary.jsx
LIVELive Preview
Console
✍ Try it yourself Wrap the Fees box in its own ErrorBoundary too. Why is it good to have small boundaries?
Each boundary isolates one area; a crash in one never blanks the others.
Complete React Course  |  Part 5  |  Advanced Patterns & React 19
M17Practice 3 of 10  •  Easy

Example 3: useId for Accessible Form Labels

● Easy💼 Real project: Reusable form components used many times
A reusable Field needs a unique id to connect its <label htmlFor> and <input id>. useId() generates one per component instance. Click a label: its own input gets focus.
App.jsx
LIVELive Preview
Console
✍ Try it yourself Click each label text. Then add a Field for "Mobile number".
Screen readers read the hint thanks to aria-describedby.
Complete React Course  |  Part 5  |  Advanced Patterns & React 19
M17Practice 4 of 10  •  Easy

Example 4: Tooltip Rendered with a Portal

● Easy💼 Real project: Help icons, chart tooltips, hover cards
On hover we measure the target with getBoundingClientRect() and render the tooltip in a portal at that position, so it is never clipped by a scroll box.
App.jsx
LIVELive Preview
Console
✍ Try it yourself Add a small arrow under the tooltip using a CSS border triangle.
A child div with border-left/right transparent and border-top dark, positioned at the bottom centre.
Complete React Course  |  Part 5  |  Advanced Patterns & React 19
M17Practice 5 of 10  •  Easy

Example 5: List with a renderItem Prop

● Easy💼 Real project: Reusable lists, tables, dropdowns
DataList handles the boring parts (empty state, numbering, borders). The caller decides how each item looks by passing a renderItem function. One component, totally different looks.
App.jsx
LIVELive Preview
Console
✍ Try it yourself Use DataList for a list of 3 courses rendered as buttons.
renderItem={(c) => <button>{c.name}</button>}
Complete React Course  |  Part 5  |  Advanced Patterns & React 19
M17Practice 6 of 10  •  Medium

Example 6: Compound Accordion

●● Medium💼 Real project: Component libraries (Radix, Headless UI style)
Accordion stores which item is open and shares it through context. Accordion.Item, .Header and .Body read it. Users of the component write clean, flexible JSX.
App.jsxAccordion.jsx
LIVELive Preview
Console
✍ Try it yourself Add an allowMultiple prop to Accordion that lets several items stay open (store an array of ids).
When allowMultiple is true, toggle adds/removes the id from an array instead of replacing it.
Complete React Course  |  Part 5  |  Advanced Patterns & React 19
M17Practice 7 of 10  •  Medium

Example 7: withAuth Higher-Order Component

●● Medium💼 Real project: Older codebases, access control
withAuth(Component) returns a NEW component that checks the login first. If the user is not logged in it shows a login prompt instead. (Today you would usually write a RequireAuth wrapper or a hook, but you will meet HOCs in existing projects.)
App.jsx
LIVELive Preview
Console
✍ Try it yourself Rewrite the same protection as a custom hook useRequireRole(role) that returns a message or null.
Many teams prefer hooks: they are easier to read and type than HOCs.
Complete React Course  |  Part 5  |  Advanced Patterns & React 19
M17Practice 8 of 10  •  Medium

Example 8: Toast System: Portal + Context

●● Medium💼 Real project: Notifications in every app
Combines two patterns: a context exposes toast() to any component, and a portal renders the stack at the top of the page. Toasts can be dismissed or disappear after 3 seconds.
App.jsxtoast.jsx
LIVELive Preview
Console
✍ Try it yourself Limit the stack to 3 toasts at a time (drop the oldest).
In toast(): setList(l => [...l, newToast].slice(-3))
Complete React Course  |  Part 5  |  Advanced Patterns & React 19
M17Practice 9 of 10  •  Hard

Example 9: Keyboard-Friendly Select (Combobox)

●●● Hard💼 Real project: Design systems, accessible forms
A reusable searchable select with full keyboard support: type to filter, Arrow Up/Down to move, Enter to choose, Escape to close. Uses useId and ARIA attributes so screen readers understand it.
App.jsxCombobox.jsx
LIVELive Preview
Console
✍ Try it yourself Use only the keyboard: Tab into the box, type "ra", press Arrow Down twice and Enter.
Then add Home/End keys to jump to the first/last option.
Complete React Course  |  Part 5  |  Advanced Patterns & React 19
M17Practice 10 of 10  •  Hard

Example 10: Optimistic Like with Rollback

●●● Hard💼 Real project: Social apps (instant likes, comments)
Show the result immediately, send the request in the background, and roll back if the server fails. This is what React 19's useOptimistic automates. Tick "Make the server fail" to see the rollback.
App.jsx
LIVELive Preview
Console
✍ Try it yourself Click like with failure ON: the heart turns red instantly, then goes back after 1.2 s with an error.
Users get instant feedback, and the data is still correct if the server rejects it.
Complete React Course  |  Part 5  |  Advanced Patterns & React 19
M17Check your understanding

Quick Quiz

Click an answer. Wrong answers shake, the right one turns green and explains why.

Q1. Why render a modal with createPortal?
✔ The portal puts the DOM elsewhere (e.g. body) while keeping it in the React tree.
Q2. What does an error boundary catch?
✔ Event handler and async errors must be caught with try/catch.
Q3. An optimistic update means...
✔ React 19 provides useOptimistic for this pattern.
🎯
Your score: 0 / 3 (first try counts)
Answer all 3 questions. Discuss any wrong answer with your partner before moving on.
Complete React Course  |  Part 5  |  Advanced Patterns & React 19
M17Module summary

Recap: What you learned

  • ✔createPortal renders modals/tooltips into document.body.
  • ✔Error boundaries show a fallback instead of crashing the whole app.
  • ✔Compound components share state through context for flexible APIs.
  • ✔Render props pass functions; HOCs wrap components (common in older code).
  • ✔useId for accessible ids; ARIA roles for custom widgets.
  • ✔React 19: Actions, useActionState, useOptimistic, use(); Server Components in frameworks.
🏆

Module 17 complete!

Finish all 10 examples and the "Try it yourself" tasks before moving on.

Practice folder: D:\react-practice\m17

➡ Next up

Module 18: TypeScript with React. Catch bugs before you even run the code.
Complete React Course  |  Part 5  |  Advanced Patterns & React 19
18
MODULE 18  •  PART 5

TypeScript with React

TypeScript adds types to JavaScript, so your editor catches mistakes like a missing prop or a wrong value BEFORE you run the app. Most React jobs today use TypeScript.

  • Why TypeScript (animated)
  • Basic types in 5 minutes
  • Typing props with type / interface
  • Optional props & defaults
  • useState<Type> and null
  • Event types for inputs & forms
  • children: React.ReactNode
  • Generics, typed context & reducers
YOU WILL BUILD:Typed GreetingStatus badgesTyped formsTyped reducerGeneric List<T>Typed useFetch<T>
🛡️
App.jsx
type Props = {
  name: string;
  marks?: number;
};

function Card({ name, marks = 0 }: Props) {
  return <p>{name}: {marks}</p>;
}
10examples
● 5 Easy
● 3 Medium
● 2 Hard
each with live code
Complete React Course  |  BrainBit Infotech, Ranchi
M18Animated explainer

Why TypeScript?

😬 Plain JavaScript

Pass marks="ninety" or forget name... no warning. The bug appears later on the student's screen as NaN or "undefined", maybe in production.
TypeScriptErrors show while you type, with exact messages. Plus autocomplete for every prop and method. Types are removed when the app is built, so users download normal JavaScript.
VS Code — StudentCard.tsx
<StudentCard name="Aman" marks="ninety" />
<StudentCard marks={92} />
Type 'string' is not assignable to type 'number'.
Property 'name' is missing in type '{ marks: number }'.


Complete React Course  |  Part 5  |  TypeScript with React
M18Crash course

TypeScript basics in 5 minutes

basics.ts
let city: string = 'Ranchi';
let marks: number = 92;
let passed: boolean = true;
let subjects: string[] = ['Maths', 'Science'];
let topper: { name: string; marks: number } = { name: 'Sneha', marks: 95 };

// union: one of several types/values
let status: 'paid' | 'pending' | 'overdue' = 'paid';
let id: number | string = 42;

// type alias & interface: name a shape
type Student = { id: number; name: string; marks?: number }; // ? = optional
interface Course { title: string; fee: number }

// function with typed parameters and return value
function percent(got: number, total: number): number {
  return (got / total) * 100;
}
TypeExample value
string"Ranchi"
number92, 3.5
booleantrue / false
string[]["a", "b"]
'a' | 'b'only "a" or "b"
T | nulla value or null
anyturns checking OFF (avoid!)
# New React + TypeScript project
D:\react-practice> npm create vite@latest my-app -- --template react-ts
Files are .tsx instead of .jsx
Complete React Course  |  Part 5  |  TypeScript with React
M18Live demo

Typing props

Describe the props with a type (or interface) and annotate the parameter: function Card({ ... }: CardProps). Optional props use ? and get a default value.
Our previews remove the types and run the code (like Vite does). Type errors show in VS Code, not here.
App.tsx
LIVELive Preview
Console
✍ Try it In VS Code, try level="Expert" or fee="free": TypeScript would underline them in red.
Complete React Course  |  Part 5  |  TypeScript with React
M18Everyday types

Typing state, events & children

useState<T>

App.jsx
// inferred from the initial value
const [count, setCount] = useState(0);

// tell TS when it cannot guess
type User = { name: string; city: string };
const [user, setUser] =
  useState<User | null>(null);
const [tags, setTags] =
  useState<string[]>([]);

user?.name  // safe: may be null

Event types

App.jsx
function onChange(
  e: React.ChangeEvent<HTMLInputElement>
) { setName(e.target.value); }

function onSubmit(
  e: React.FormEvent<HTMLFormElement>
) { e.preventDefault(); }

function onClick(
  e: React.MouseEvent<HTMLButtonElement>
) {}

Tip: hover over onChange in VS Code to see the exact type.

children & functions

App.jsx
type PanelProps = {
  title: string;
  children: React.ReactNode;
  onClose?: () => void;
  onSave: (id: number) => void;
};

function Panel({ title, children,
                 onClose }: PanelProps) {
  ...
}
Complete React Course  |  Part 5  |  TypeScript with React
M18Practice 1 of 10  •  Easy

Example 1: Typed Greeting Component

● Easy💼 Real project: Every TypeScript React project
The simplest typed component: a GreetingProps type with a required name and an optional emoji. In VS Code, typing <Greeting shows autocomplete for both props.
App.tsx
LIVELive Preview
Console
✍ Try it yourself Add a required age: number prop and show it. Every Greeting must now pass an age (TypeScript enforces it).
Add age: number; to the type and age={15} to each usage.
Complete React Course  |  Part 5  |  TypeScript with React
M18Practice 2 of 10  •  Easy

Example 2: Optional Props with Defaults (Badge)

● Easy💼 Real project: Design system components
A Badge where only label is required. color and size are optional with defaults. size is a union so only 3 sizes are allowed.
App.tsx
LIVELive Preview
Console
✍ Try it yourself Add a size "xl" (22px). TypeScript forces you to add it to BOTH the Size type and the fontSizes record.
Record<Size, number> must contain every Size key, so TS reminds you.
Complete React Course  |  Part 5  |  TypeScript with React
M18Practice 3 of 10  •  Easy

Example 3: Typed State: number, string[] and User | null

● Easy💼 Real project: Any stateful component
Three kinds of state: a number (inferred), a string[] list, and a User | null that starts empty. Optional chaining user?.name handles null safely.
App.tsx
LIVELive Preview
Console
✍ Try it yourself In VS Code, try setSkills([1, 2]) or setUser({ name: 'X' }): both are errors. Why?
Numbers are not strings, and a User needs city and points too.
Complete React Course  |  Part 5  |  TypeScript with React
M18Practice 4 of 10  •  Easy

Example 4: Typed Event Handlers

● Easy💼 Real project: Forms and inputs in TS projects
Each handler declares its event type: ChangeEvent<HTMLInputElement>, ChangeEvent<HTMLSelectElement> and FormEvent<HTMLFormElement>. Now e.target.value autocompletes.
App.tsx
LIVELive Preview
Console
✍ Try it yourself Add a checkbox handler with e.target.checked typed as ChangeEvent<HTMLInputElement>.
Same event type as the text input, but read checked instead of value.
Complete React Course  |  Part 5  |  TypeScript with React
M18Practice 5 of 10  •  Easy

Example 5: Order Status with a Union Type

● Easy💼 Real project: Delivery tracking, payment states
type Status = 'placed' | 'shipped' | 'delivered' | 'cancelled' means a typo like 'shiped' is impossible. A Record<Status, ...> must cover every status.
App.tsx
LIVELive Preview
Console
✍ Try it yourself Add a status "returned". TypeScript (in VS Code) shows an error in look until you add its icon and colour.
That is the power of Record<Status, ...>: you cannot forget a case.
Complete React Course  |  Part 5  |  TypeScript with React
M18Practice 6 of 10  •  Medium

Example 6: Typed Product List (Product[])

●● Medium💼 Real project: E-commerce catalogue
An interface Product describes each item; the list component receives products: Product[] and an onAdd: (p: Product) => void callback. Everything that touches a product is checked.
App.tsx
LIVELive Preview
Console
✍ Try it yourself Add a discount?: number field to Product and show the discounted price when it exists.
p.discount ? p.price * (1 - p.discount / 100) : p.price
Complete React Course  |  Part 5  |  TypeScript with React
M18Practice 7 of 10  •  Medium

Example 7: Typed Reducer with Discriminated Unions

●● Medium💼 Real project: Complex state in TS apps
Each action type has its own payload shape: { type: 'add'; text: string }, { type: 'toggle'; id: number }. Inside each case, TypeScript knows exactly which fields exist.
App.tsx
LIVELive Preview
Console
✍ Try it yourself In VS Code try dispatch({ type: 'toggle' }) without an id: TypeScript refuses. Add a rename action.
| { type: 'rename'; id: number; text: string } plus its case.
Complete React Course  |  Part 5  |  TypeScript with React
M18Practice 8 of 10  •  Medium

Example 8: Typed AuthContext with a Safe Hook

●● Medium💼 Real project: Authentication in TS apps
The context value has a type AuthContextType. The context starts as null, and useAuth() throws a clear error if used outside the provider, so components always get a non-null value.
App.tsxAuthContext.tsx
LIVELive Preview
Console
✍ Try it yourself Add a third role "trainer" to the Role type and a login button for it.
Only the type and one button change; TS checks every place roles are used.
Complete React Course  |  Part 5  |  TypeScript with React
M18Practice 9 of 10  •  Hard

Example 9: Generic List<T> Component

●●● Hard💼 Real project: Reusable tables and lists in big codebases
A generic component works with ANY item type while staying type-safe. List<T> takes items: T[], a getKey and a renderItem(item: T). TypeScript infers T from the items you pass.
App.tsx
LIVELive Preview
Console
✍ Try it yourself Reuse List for an array of 3 course objects { slug, title, fee }.
Define a Course type and pass getKey={(c) => c.slug}. T is inferred as Course.
Complete React Course  |  Part 5  |  TypeScript with React
M18Practice 10 of 10  •  Hard

Example 10: Typed useFetch<T> Hook

●●● Hard💼 Real project: API layers in production apps
A generic hook: useFetch<Weather>(url) returns { data: Weather | null, loading, error }. API response types live in one place (types.ts), so a backend change shows errors everywhere it matters.
App.tsxuseFetch.tstypes.ts
LIVELive Preview
Console
✍ Try it yourself Add a User interface for /api/users/1 and a ProfileCard using useFetch<User>.
Fields: id, name, email, city, role, joined, courses.
Complete React Course  |  Part 5  |  TypeScript with React
M18Check your understanding

Quick Quiz

Click an answer. Wrong answers shake, the right one turns green and explains why.

Q1. What does marks?: number mean in a props type?
✔ The ? makes the prop optional.
Q2. How do you type state that starts empty but will hold a User?
✔ Tell TS both possibilities: User or null.
Q3. Do browsers run TypeScript directly?
✔ Vite/esbuild strip types; type checking happens in your editor and with tsc.
🎯
Your score: 0 / 3 (first try counts)
Answer all 3 questions. Discuss any wrong answer with your partner before moving on.
Complete React Course  |  Part 5  |  TypeScript with React
M18Module summary

Recap: What you learned

  • ✔TypeScript catches mistakes in the editor; the build outputs plain JS.
  • ✔Type props with type/interface; ? for optional props.
  • ✔useState<T> when the initial value is not enough (e.g. User | null).
  • ✔React event types: ChangeEvent, FormEvent, MouseEvent.
  • ✔Unions and Record make impossible states impossible.
  • ✔Generics (List<T>, useFetch<T>) give reusable, type-safe code.
🏆

Module 18 complete!

Finish all 10 examples and the "Try it yourself" tasks before moving on.

Practice folder: D:\react-practice\m18

➡ Next up

Module 19: Testing React Apps. Prove your components work, automatically.
Complete React Course  |  Part 5  |  TypeScript with React
19
MODULE 19  •  PART 5

Testing React Apps

Tests are small programs that check your app works, every time you change code. Companies will not merge code without them. Learn Vitest + React Testing Library, the modern standard.

  • Why test? The testing pyramid
  • Setting up Vitest + Testing Library
  • describe, test, expect
  • Finding elements the way users do
  • Simulating clicks and typing
  • Async tests with findBy
  • Mocking functions and fetch
  • Red, green, refactor (TDD)
YOU WILL BUILD:Heading testCounter testForm validation testMocked API testTodo flow testTDD discount calculator
✅
App.jsx
test('adds one on click', () => {
  render(<Counter />);
  fireEvent.click(screen.getByRole('button'));
  expect(screen.getByText('Count: 1'))
    .toBeInTheDocument();
});
10examples
● 5 Easy
● 3 Medium
● 2 Hard
each with live code
Complete React Course  |  BrainBit Infotech, Ranchi
M19Big picture

Why write tests?

E2E Integration Unit & component tests
LevelTests...Tool
Unitone function or componentVitest + Testing Library
Integrationcomponents working togetherVitest + Testing Library
End-to-endthe real app in a browserPlaywright, Cypress
🛡️

Safety net

Change code confidently: if you break something, a test turns red in seconds.
⏱️

Saves time

No more clicking through 20 screens by hand after every change.
📝

Living documentation

A test like "shows error when phone has 9 digits" explains how the app should behave.
💼

Job skill

Pull requests in companies run tests automatically (CI). Red tests = cannot merge.
Complete React Course  |  Part 5  |  Testing React Apps
M19Tools

Setup: Vitest + React Testing Library

D:\react-practice> npm install -D vitest jsdom @testing-library/react
D:\react-practice> npm install -D @testing-library/jest-dom @testing-library/user-event
added 54 packages
config
// vite.config.js
export default defineConfig({
  plugins: [react()],
  test: {
    environment: 'jsdom',          // a fake browser
    globals: true,
    setupFiles: './src/setupTests.js',
  },
});

// src/setupTests.js
import '@testing-library/jest-dom/vitest';
package.json
// package.json
"scripts": {
  "dev": "vite",
  "test": "vitest"
}
D:\react-practice> npm test
✓ src/Counter.test.jsx (3 tests) 41ms
Test Files 1 passed (1)
Tests 3 passed (3)
In real projectsTest files sit next to components: Counter.jsx + Counter.test.jsx. Vitest finds every *.test.jsx file and re-runs on save.
Key ideaIn these slides a built-in mini test runner executes the tests live, using the same API (render, screen, fireEvent, expect, vi).
Complete React Course  |  Part 5  |  Testing React Apps
M19Live tests

Anatomy of a test

render puts the component in a fake page; screen finds elements; fireEvent acts like a user; expect checks the result. describe groups related tests. The preview below is the test report.
Counter.test.jsxCounter.jsx
LIVELive Preview
Console
✍ Try it Open Counter.jsx in the Lab and change count + 1 to count + 2. Run: two tests fail. That is the safety net!
Complete React Course  |  Part 5  |  Testing React Apps
M19Queries

Find elements the way users do

Query (best first)Finds byExample
getByRolerole + accessible namegetByRole('button', { name: /save/i })
getByLabelTextthe label of an inputgetByLabelText('Email')
getByPlaceholderTextplaceholdergetByPlaceholderText('Search...')
getByTextvisible textgetByText('Order placed')
getByTestIddata-testid (last resort)getByTestId('cart-count')
PrefixIf not foundUse for
getBythrows errorelement must be there
queryByreturns nullchecking something is NOT there
findBywaits (async)things that appear later (API data)
getAllByreturns an arraylists
Key ideaTesting Library's rule: "The more your tests resemble the way your software is used, the more confidence they can give you." Test what the user sees, not internal state.
Complete React Course  |  Part 5  |  Testing React Apps
M19Animated explainer

Red, Green, Refactor (Test-Driven Development)

🔴 RED

Write a test for behaviour that does not exist yet. Run it: it FAILS.
App.jsx
test('10% off above Rs 1000', () => {
  expect(discount(2000)).toBe(200);
});
// ✗ discount is not defined

🟢 GREEN

Write the simplest code that makes the test pass.
App.jsx
function discount(total) {
  return total > 1000 ? total * 0.1 : 0;
}
// ✓ passes

🔵 REFACTOR

Clean up the code. The test stays green, proving you did not break anything.
App.jsx
const LIMIT = 1000, RATE = 0.1;
export const discount = (t) =>
  t > LIMIT ? t * RATE : 0;
// ✓ still passes
🔄 repeat for the next small feature
Complete React Course  |  Part 5  |  Testing React Apps
M19Practice 1 of 10  •  Easy

Example 1: Test: Heading Renders

● Easy💼 Real project: The first test in every project
Render the component and check the heading is on the page using getByRole('heading'). If someone deletes or renames the title by mistake, this test fails.
Welcome.test.jsxWelcome.jsx
LIVELive Preview
Console
✍ Try it yourself Add a third test checking the paragraph text "Learn coding in Ranchi" with getByText.
expect(screen.getByText('Learn coding in Ranchi')).toBeInTheDocument();
Complete React Course  |  Part 5  |  Testing React Apps
M19Practice 2 of 10  •  Easy

Example 2: Test: Counter Click

● Easy💼 Real project: Testing interactions
fireEvent.click simulates a user click. After each click we expect the new text. One test can check several steps in order.
LikeButton.test.jsxLikeButton.jsx
LIVELive Preview
Console
✍ Try it yourself Write a test that clicks 3 times and expects 11 likes (liked state).
Odd number of clicks = liked.
Complete React Course  |  Part 5  |  Testing React Apps
M19Practice 3 of 10  •  Easy

Example 3: Test: Props Change the Output

● Easy💼 Real project: Reusable components with many variants
Test the same component with different props using rerender or separate renders. Here we check a Greeting and a PriceTag that formats Indian Rupees.
Greeting.test.jsxcomponents.jsx
LIVELive Preview
Console
✍ Try it yourself Add a test: <PriceTag amount={2500000} /> shows "Rs 25,00,000".
One more render + expect.
Complete React Course  |  Part 5  |  Testing React Apps
M19Practice 4 of 10  •  Easy

Example 4: Test: Empty State vs List

● Easy💼 Real project: Conditional rendering
Use queryBy to check something is NOT on screen (it returns null instead of throwing). Use getAllByRole('listitem') to count list items.
Orders.test.jsxOrders.jsx
LIVELive Preview
Console
✍ Try it yourself Add a heading "Your orders (N)" to the list version and test the number in it.
expect(screen.getByRole('heading')).toHaveTextContent('(3)')
Complete React Course  |  Part 5  |  Testing React Apps
M19Practice 5 of 10  •  Easy

Example 5: Test: Typing in an Input

● Easy💼 Real project: Forms and search boxes
userEvent.type types letter by letter like a real user. We find the input by its label (good for accessibility) and check the live preview text.
NameForm.test.jsxNameForm.jsx
LIVELive Preview
Console
✍ Try it yourself Add a test: after typing and then clearing the input (user.clear(input)), the text "Type your name" is back.
await user.clear(input); expect(screen.getByText('Type your name')).toBeInTheDocument();
Complete React Course  |  Part 5  |  Testing React Apps
M19Practice 6 of 10  •  Medium

Example 6: Test: Callback Prop Was Called (vi.fn)

●● Medium💼 Real project: Components that report events to parents
vi.fn() creates a mock function that records every call. We pass it as onAdd and assert it was called once with the right product.
ProductCard.test.jsxProductCard.jsx
LIVELive Preview
Console
✍ Try it yourself Add an onWishlist prop and a "❤️ Wishlist" button, then test it with a second vi.fn().
Same pattern: create the mock, render, click, expect toHaveBeenCalledWith(product).
Complete React Course  |  Part 5  |  Testing React Apps
M19Practice 7 of 10  •  Medium

Example 7: Test: Mocked fetch with findBy

●● Medium💼 Real project: Components that load API data
We replace fetch with a mock that returns fake students, so the test is fast and does not need a server. findByText waits until the data appears. We also test the error path.
StudentList.test.jsxStudentList.jsx
LIVELive Preview
Console
✍ Try it yourself Add a test for an EMPTY array response: the component should show "No students yet" (update the component too).
Mock json to return [] and add if (students.length === 0) return <p>No students yet</p>.
Complete React Course  |  Part 5  |  Testing React Apps
M19Practice 8 of 10  •  Medium

Example 8: Test: Form Validation Messages

●● Medium💼 Real project: Login, sign-up, payment forms
We test the rules from the user's point of view: submit an empty form → errors appear; type valid data → errors disappear and onSubmit receives the values.
Login.test.jsxLogin.jsx
LIVELive Preview
Console
✍ Try it yourself Add a rule "password needs a number" in Login.jsx, then write a failing test first, then make it pass.
Test: type "abcdefgh" and expect the message "Add at least one number".
Complete React Course  |  Part 5  |  Testing React Apps
M19Practice 9 of 10  •  Hard

Example 9: Test: Full Todo Flow

●●● Hard💼 Real project: Integration tests of a whole feature
An integration test walks through the feature like a user: add two todos, complete one, filter, delete. It uses within() to search inside one list item. If any part of the flow breaks, this test catches it.
Todos.test.jsxTodos.jsx
LIVELive Preview
Console
✍ Try it yourself Break the app on purpose (e.g. make Add ignore the text) and watch which step of the test fails. Then fix it.
Good tests point to exactly where things went wrong.
Complete React Course  |  Part 5  |  Testing React Apps
M19Practice 10 of 10  •  Hard

Example 10: TDD: Discount Calculator

●●● Hard💼 Real project: Business rules for billing (coupons, GST)
The tests were written FIRST from the shop's rules: 10% off above Rs 1,000, coupon RANCHI20 gives 20% (max Rs 500), GST 12% on the discounted amount. The component and the pure function were then written to make every test green.
pricing.test.jsxpricing.jsCheckout.jsx
LIVELive Preview
Console
✍ Try it yourself New rule from the shop owner: students with coupon "STUDENT" get flat Rs 150 off. Write the test first (red), then update pricing.js (green).
expect(calculateBill(800, 'STUDENT').discount).toBe(150), then add an else-if branch.
Complete React Course  |  Part 5  |  Testing React Apps
M19Check your understanding

Quick Quiz

Click an answer. Wrong answers shake, the right one turns green and explains why.

Q1. Which query should you try FIRST?
✔ getByRole finds elements the way users and screen readers do.
Q2. Data appears after an API call. Which query waits for it?
✔ findBy* returns a promise that resolves when the element appears.
Q3. What does vi.fn() create?
✔ Use it to check callbacks were called, and to fake fetch.
🎯
Your score: 0 / 3 (first try counts)
Answer all 3 questions. Discuss any wrong answer with your partner before moving on.
Complete React Course  |  Part 5  |  Testing React Apps
M19Module summary

Recap: What you learned

  • ✔Tests are a safety net: most should be fast unit/component tests.
  • ✔Vitest runs tests; React Testing Library renders and queries components.
  • ✔Arrange (render) → Act (click/type) → Assert (expect).
  • ✔Prefer getByRole / getByLabelText; queryBy for absence; findBy for async.
  • ✔Mock functions and fetch with vi.fn() to test in isolation.
  • ✔TDD: red → green → refactor, in small steps.
🏆

Module 19 complete!

Finish all 10 examples and the "Try it yourself" tasks before moving on.

Practice folder: D:\react-practice\m19

➡ Next up

Module 20: Capstone Projects & Deployment. Build complete apps and put them online.
Complete React Course  |  Part 5  |  Testing React Apps
20
MODULE 20  •  PART 5

Capstone Projects & Deployment

Time to build complete apps and put them on the internet. Ten projects from small to large, plus how to plan, structure, deploy and present your work to get hired.

  • Planning a project step by step
  • Real-world folder structure
  • Build & deploy (Netlify, Vercel, GitHub Pages)
  • Environment variables per stage
  • Next.js: when to use it
  • Accessibility & SEO checklist
  • Your portfolio & career roadmap
  • 10 complete capstone projects
YOU WILL BUILD:Visiting cardBill splitterNotes appWeather dashboardExpense trackerResult dashboardMini ERP
🚀
Terminal
npm run build
# dist/ folder is ready
# drag it to Netlify
# -> https://my-app.netlify.app
10examples
● 5 Easy
● 3 Medium
● 2 Hard
each with live code
Complete React Course  |  BrainBit Infotech, Ranchi
M20Animated explainer

How professionals plan a project

💡
Ideaproblem + users
→
✏️
Wireframesketch screens
→
🧩
Componentsdraw the tree
→
💾
State & dataminimal state, APIs
→
🔨
Buildstatic first, then interactive
→
✅
Testkey flows
→
🌐
Deployshare the link
Example: Expense Tracker
Usersstudents tracking pocket money
Screensdashboard, add form, history, chart
Statetransactions[] (everything else derived)
StoragelocalStorage (later: a backend)
In real projectsCommit to Git after every step and push to GitHub. Recruiters look at your commit history and README, not just the final app!
Complete React Course  |  Part 5  |  Capstone Projects & Deployment
M20Structure

Real-world folder structure (feature-based)

📁 src/
  📁 app/App.jsx, routes, providers
  📁 components/shared UI: Button, Modal, Card
  📁 features/one folder per feature
    📁 cart/CartPage.jsx, cartSlice.js, useCart.js, cart.test.jsx
    📁 auth/LoginPage.jsx, AuthContext.jsx
  📁 hooks/useFetch, useDebounce
  📁 services/api.js: all fetch calls in one place
  📁 utils/formatRupees, dates
  📁 assets/images, icons
  📄 main.jsx
📄 .envVITE_API_URL=...
📦

Group by feature

Everything about the cart lives together. Easy to find, easy to delete or move.
🌐

One API layer

services/api.js exports getProducts(), createOrder(). Components never write URLs.
🏷️

Naming

Components: PascalCase.jsx. Hooks: useCamelCase.js. Tests next to the file they test.
Complete React Course  |  Part 5  |  Capstone Projects & Deployment
M20Go live

Build & deploy your app (free)

D:\react-practice> npm run build
vite v6 building for production...
dist/index.html 0.46 kB
dist/assets/index-a1b2c3.js 143.20 kB
built in 2.31s
D:\react-practice> npm run preview
Local: http://localhost:4173/ (test the build)
Key ideaThe dist folder contains plain HTML, CSS and JS. Any static host can serve it.
HostHowGood for
NetlifyDrag & drop dist on app.netlify.com, or connect GitHubFastest first deploy
VercelImport the GitHub repo, auto-deploys every pushVite & Next.js apps
GitHub PagesSet base in vite.config, push dist with gh-pagesPortfolio projects
Your server / VPSCopy dist to Nginx/ApacheClient & government projects
Common mistakeUsing React Router? Configure the host to send every URL to index.html (Netlify: a _redirects file with /* /index.html 200). Otherwise refreshing /courses gives a 404.
Complete React Course  |  Part 5  |  Capstone Projects & Deployment
M20Polish

Before you launch: quality checklist

♿ Accessibility

  • Every image has alt
  • Inputs have labels
  • Use real <button> for clicks
  • Works with keyboard only (Tab, Enter, Esc)
  • Colour contrast is readable

🔍 SEO & sharing

  • Good <title> and meta description
  • One <h1> per page
  • Open Graph image for WhatsApp/LinkedIn previews
  • Need Google ranking? Consider Next.js (server rendering)

⚡ Performance & safety

  • Lighthouse score in Chrome DevTools
  • Compress images (WebP)
  • Lazy-load heavy pages
  • No secrets in front-end code or .env
  • Friendly loading & error states
In real projectsRun Lighthouse: Chrome DevTools (F12) > Lighthouse > Analyze page load. Aim for 90+ in each category.
Key ideaTest on a real phone with mobile data. Many users in Tier 2/3 cities browse on budget phones.
Complete React Course  |  Part 5  |  Capstone Projects & Deployment
M20What next

Your career roadmap & portfolio

Suggested learning path

Month 1-2
HTML, CSS, JavaScript
Month 3-4
React core (Parts 1-3)
Month 5
Router, state, performance
Month 6
TypeScript + testing
Month 7
Next.js or Node.js backend
Month 8+
Portfolio, freelancing, job applications
📁

Portfolio of 3-5 projects

Live links + GitHub code + a README with screenshots, features and tech used.
💼

Where to apply

LinkedIn, Naukri, Internshala, Wellfound; freelance on Upwork. Local businesses in Ranchi need websites too!
🎤

Interview topics

useState vs useRef, useEffect deps, keys, lifting state, Context vs Redux, memo, custom hooks, routing, testing.
Complete React Course  |  Part 5  |  Capstone Projects & Deployment
M20Practice 1 of 10  •  Easy

Example 1: Digital Visiting Card Generator

● Easy💼 Real project: Freelancers, small shop owners
Project 1: a form on the left, a live business card on the right, with colour themes. Concepts: controlled inputs, one state object, conditional styles.
App.jsxApp.css
LIVELive Preview
Console
✍ Try it yourself Add a "Website" field and a dark theme. Bonus: a "Download" button that copies the card details as text to the clipboard.
navigator.clipboard.writeText(...) with the card values joined by new lines.
Complete React Course  |  Part 5  |  Capstone Projects & Deployment
M20Practice 2 of 10  •  Easy

Example 2: Restaurant Bill Splitter

● Easy💼 Real project: Friends sharing a bill at a cafe
Project 2: enter the bill, tip % and number of friends; get each person's share. Concepts: number inputs, derived values, input validation, Indian currency formatting.
App.jsx
LIVELive Preview
Console
✍ Try it yourself Add a "Who paid?" dropdown with friend names and show "Aman pays Rs X to Priya" style messages.
Keep a list of names; everyone except the payer owes each to the payer.
Complete React Course  |  Part 5  |  Capstone Projects & Deployment
M20Practice 3 of 10  •  Easy

Example 3: Unit Converter

● Easy💼 Real project: Students & shopkeepers (kg/lb, km/miles, Celsius/Fahrenheit)
Project 3: choose a category, type a value, see the conversion. Concepts: config objects drive the UI, select inputs, lifting the swap logic, derived results.
App.jsx
LIVELive Preview
Console
✍ Try it yourself Add a "Temperature" category. It cannot use simple multiplication: handle it with special formulas.
Write a function convertTemp(value, from, to) and use it when cat === 'Temperature'.
Complete React Course  |  Part 5  |  Capstone Projects & Deployment
M20Practice 4 of 10  •  Easy

Example 4: Notes App with localStorage

● Easy💼 Real project: Google Keep style note taking
Project 4: create, colour, pin, search and delete notes; everything is saved in localStorage. Concepts: arrays of objects in state, the useLocalStorage hook, sorting pinned first, empty states.
App.jsxuseLocalStorage.js
LIVELive Preview
Console
✍ Try it yourself Add editing: double-click a note to edit its text in a textarea.
Keep an editingId state; render a textarea for that note and save on blur.
Complete React Course  |  Part 5  |  Capstone Projects & Deployment
M20Practice 5 of 10  •  Easy

Example 5: Flashcards for Exam Revision

● Easy💼 Real project: Study apps (Anki, Quizlet)
Project 5: a deck of cards that flip with a 3D animation, Next/Previous, shuffle and "I knew it" scoring. Concepts: index state, CSS 3D transforms driven by state, derived progress.
App.jsxApp.css
LIVELive Preview
Console
✍ Try it yourself Load the cards from /api/quiz instead of the hard-coded deck (question + correct option).
Fetch in an effect and map each item to [q, options[answer]].
Complete React Course  |  Part 5  |  Capstone Projects & Deployment
M20Practice 6 of 10  •  Medium

Example 6: Weather Dashboard (Multi-City)

●● Medium💼 Real project: Travel planning, agriculture apps
Project 6: add cities to a dashboard; each card fetches its own weather from /api/weather; remove cities; the list is saved. Concepts: useFetch-style hook per card, errors per card, localStorage, derived summary.
App.jsx
LIVELive Preview
Console
✍ Try it yourself Add a summary bar above the cards: hottest and coolest city. (Hint: lift the weather data up, or fetch all cities in the parent.)
Fetch all cities with Promise.all in the parent and pass data down; then derive max/min.
Complete React Course  |  Part 5  |  Capstone Projects & Deployment
M20Practice 7 of 10  •  Medium

Example 7: Expense Tracker with Chart

●● Medium💼 Real project: Personal finance, shop accounts
Project 7: add income/expenses by category and month; see balance cards and an animated SVG bar chart per category. Concepts: reducer, derived totals, grouping data, SVG charts in React.
App.jsxChart.jsx
LIVELive Preview
Console
✍ Try it yourself Add a transaction list with delete buttons, and a warning banner when spending is more than 70% of income.
spent / income > 0.7 → show a red banner. Delete with dispatch({ type: 'remove', id }).
Complete React Course  |  Part 5  |  Capstone Projects & Deployment
M20Practice 8 of 10  •  Medium

Example 8: Course Search & Favourites

●● Medium💼 Real project: Course platforms (Udemy, Coursera style)
Project 8: search, filter by level and price, sort, and favourite courses (saved). Concepts: multiple filters combined, derived lists, Set in state, localStorage, empty states.
App.jsxcourses.js
LIVELive Preview
Console
✍ Try it yourself Add sorting (fee low-high, duration) and a "Clear filters" button that resets everything.
One more state for sort and a function that resets all filter states to defaults.
Complete React Course  |  Part 5  |  Capstone Projects & Deployment
M20Practice 9 of 10  •  Hard

Example 9: Student Result Dashboard with Charts

●●● Hard💼 Real project: School ERP analytics
Project 9: loads students from the API, calculates grades, class average, pass percentage, a grade distribution donut, a marks bar chart and a sortable table. Concepts: fetch + loading, heavy derived data with useMemo, SVG charts, sorting.
App.jsxcharts.jsx
LIVELive Preview
Console
✍ Try it yourself Add a class filter (10-A, 10-B, 10-C) that updates every number and chart. Only the data changes; the charts are reusable!
Filter students by s.class before computing stats (and include the filter in the useMemo deps).
Complete React Course  |  Part 5  |  Capstone Projects & Deployment
M20Practice 10 of 10  •  Hard

Example 10: Coaching Institute Mini-ERP

●●● Hard💼 Real project: Real client projects for institutes & schools
Project 10 (final capstone): a routed admin app with a dashboard, a students page (add, search, delete), a fees page (mark paid, totals) and an auth guard. State lives in a Context + reducer store. This is the shape of real freelance projects.
App.jsxstore.jsxpages.jsx
LIVELive Preview
Console
✍ Try it yourself Extend it: an Attendance page, editing a student, and saving the whole store to localStorage. Then deploy it to Netlify and add it to your portfolio!
Use the reducer's third argument (init) to load from localStorage, and an effect in StoreProvider to save.
Complete React Course  |  Part 5  |  Capstone Projects & Deployment
M20Check your understanding

Quick Quiz

Click an answer. Wrong answers shake, the right one turns green and explains why.

Q1. What does npm run build create?
✔ Upload dist/ to any static host like Netlify or Vercel.
Q2. Your routed app shows 404 when refreshing /courses on Netlify. Why?
✔ Add a _redirects rule: /* /index.html 200.
Q3. What is the best first step for a new project?
✔ A clear plan makes the code simpler and faster to write.
🎯
Your score: 0 / 3 (first try counts)
Answer all 3 questions. Discuss any wrong answer with your partner before moving on.
Complete React Course  |  Part 5  |  Capstone Projects & Deployment
M20Module summary

Recap: What you learned

  • ✔Plan: idea → wireframe → components → state → build → test → deploy.
  • ✔Organise code by feature; keep API calls in a services layer.
  • ✔npm run build → deploy dist/ to Netlify, Vercel or GitHub Pages.
  • ✔Check accessibility, SEO and performance (Lighthouse) before launch.
  • ✔Build a portfolio of 3-5 live projects with good READMEs.
  • ✔Next steps: Next.js, Node.js/Express backends, React Native for mobile apps.
🏆

Module 20 complete!

Finish all 10 examples and the "Try it yourself" tasks before moving on.

Practice folder: D:\react-practice\m20

➡ Next up

You have completed the course. Build, deploy and share your projects. All the best from BrainBit Infotech, Ranchi! 🎉
Complete React Course  |  Part 5  |  Capstone Projects & Deployment
🎓
COURSE COMPLETE

Congratulations, React Developer!

You finished 20 modules and 200 practice examples: from your first component to Redux, TypeScript, testing and deployed capstone projects.

CERTIFICATE OF COMPLETION
This certifies that
Student Name
has successfully completed the Complete React Course (Beginner to Advanced)
BrainBit Infotech, RanchiTrainer: Nandan KumarDate: ____________

Click the name to type it, then print this slide (Ctrl + P) or take a screenshot.

</> React Code Lab

Console