Notifications

No notifications

/Phase 3

React Basics

React — Building UIs with Components

React is a JavaScript library for building declarative, component-based user interfaces. Instead of manipulating the DOM directly, you describe *what* should render and React efficiently updates the real DOM through a virtual DOM diffing algorithm.

JSX — JavaScript + XML

JSX lets you write HTML-like syntax inside JavaScript. It compiles to React.createElement() calls.

const title = <h1 className="heading">Hello, React!</h1>;
// Compiles to:
// React.createElement("h1", { className: "heading" }, "Hello, React!")

Functional Components

Components are JavaScript functions that return JSX. They accept props as input.

FeatureDescription
PropsRead-only inputs passed from parent
JSX ReturnMust return a single root element (or Fragment)
NamingPascalCase (MyComponent)
PureSame props → same output

Rendering Lists

Use .map() to transform arrays into elements. Always provide a unique key prop.

const items = ["Apple", "Banana", "Cherry"];
const list = items.map((item, i) => <li key={i}>{item}</li>);

Conditional Rendering

PatternExample
Ternary{isOn ? : }
Logical AND{show && }
Early returnif (!data) return

Fragments

(or <>…) lets you group elements without adding extra DOM nodes.

On this page

Detailed Theory

What React Actually Is

React is a JavaScript library that lets you build a UI by writing components — small, reusable pieces of UI that look like HTML inside JavaScript. Instead of telling the browser "create this div, then update it, then remove it" (imperative), you describe what the UI should look like for the current data, and React figures out the DOM updates for you (declarative).

If your data changes, you re-describe the UI; React diffs the difference and updates the page.

Your First Component

A component is just a function that returns JSX:

function Welcome() {
  return <h1>Hello, world!</h1>;
}

Use it anywhere by calling it like a tag:

<Welcome />

Two non-negotiable rules:

1. Component names must start with a Capital Letter (Welcome, not welcome). Lowercase names are treated as HTML. 2. A component must return one element. Wrap multiple in a fragment: <>….

JSX — HTML Inside JavaScript

JSX is *not* a string and not HTML. It's syntactic sugar that compiles to React.createElement(...) calls.

const name = "Asha";
const element = <h1 className="title">Hi, {name}!</h1>;

JSX rules to remember:

  • className instead of class
  • htmlFor instead of for
  • Self-close empty tags: ,
  • Expressions go inside curly braces: {value}
  • Inline styles are objects: style={{ color: "red", fontSize: 14 }} (camelCase keys)
  • You can put any JS expression in { } — but not statements (no if, no for)

Props — Passing Data In

Props are how a parent gives data to a child:

function Greeting({ name, age }) {
  return <p>Hi {name}, you are {age}.</p>;
}

<Greeting name="Asha" age={21} />

Props are read-only. A child must never mutate props.name — if you need to change it, the parent owns that data.

The Special children Prop

Anything between a component's opening and closing tags arrives as children:

function Card({ children }) {
  return <div className="card">{children}</div>;
}

<Card> <h3>Title</h3> <p>Body text…</p> </Card>

children is the bedrock of layout components, modals, and slot patterns.

Conditional Rendering

Plain JavaScript inside { }:

{isLoggedIn ? <Dashboard /> : <Login />}
{count > 0 && <p>You have {count} items</p>}
{error && <Alert message={error} />}

Watch out: {count &&

} renders 0 when count is 0 (because 0 is falsy but still rendered). Use count > 0 && … instead.

Rendering Lists

{users.map((user) => (
  <li key={user.id}>{user.name}</li>
))}

The key prop is essential. It tells React which item is which between renders so it can reuse DOM nodes.

Good keysBad keys
Unique stable IDs (user.id)Array index (breaks on reorder/delete)
UUIDs from your dataMath.random() (different every render)

Handling Events

Use camelCase event names and pass a function reference (not a call):

function Button() {
  function handleClick() {
    alert("clicked!");
  }
  return <button onClick={handleClick}>Save</button>;
}

Inline arrow when you need parameters:

<button onClick={() => deleteItem(item.id)}>×</button>

Beginner Mistakes to Skip

1. Calling the function instead of passing it: onClick={handleClick()} runs immediately. Drop the parens. 2. Forgetting key on lists — React logs a warning and your list updates may glitch. 3. Mutating props — props are read-only. Treat them like inputs to a pure function. 4. Returning two top-level elements without a fragment — JSX requires one root. 5. Using for and if directly inside JSX — they're statements. Move them above the return, or use map / ternaries.

Intermediate: How Re-Rendering Works (Three Phases)

When state changes, React goes through:

1. RENDER         — call your function, build a Virtual DOM tree (plain JS objects)
2. RECONCILIATION — diff new VDOM vs previous to find what actually changed
3. COMMIT         — apply ONLY the changed nodes to the real DOM

The Virtual DOM isn't magic; it's just objects in memory. The win is that diffing JS objects is fast, and minimal real-DOM changes are slow only when you make them. React is doing the bookkeeping.

Intermediate: Reconciliation Rules of Thumb

  • Different element type at the same position → destroy the old subtree and rebuild.
  • Same type, different props → reuse the DOM node, only change props.
  • Lists with stable keys → reorder DOM nodes instead of recreating them.
This is exactly why bad keys hurt: React thinks "item 2 changed" when really "item 2 became item 1".

Intermediate: Composition Over Inheritance

React deliberately has no class inheritance for components. You compose instead:

function Modal({ title, children, footer }) {
  return (
    <div className="modal">
      <h2>{title}</h2>
      <div>{children}</div>
      <footer>{footer}</footer>
    </div>
  );
}

<Modal title="Confirm" footer={<button>OK</button>}> Are you sure? </Modal>

Two patterns you'll see everywhere:

  • children prop — generic slot
  • Named slot props (like footer above) — multiple slots
  • Render props — pass a function that returns JSX (less common since hooks)

Intermediate: Pure Components & Idempotent Renders

Treat every component like a *pure function* of its props and state. The same input must produce the same output. Side effects (fetch, timers, DOM mutations) belong in useEffect — never in the render body.

Why? React may render your component twice in dev (Strict Mode) to catch impurities. If your component holds onto a counter outside state, you'll see double-counts.

Advanced: Fragments, Portals & Lazy

// Fragment — group without adding a DOM node
<>
  <Header />
  <Main />
</>

// Portal — render into a DOM node OUTSIDE your component tree (modals, tooltips) import { createPortal } from "react-dom"; return createPortal(<Modal />, document.getElementById("modal-root"));

// Lazy — code-split a component so it loads only when used import { lazy, Suspense } from "react"; const Settings = lazy(() => import("./Settings"));

<Suspense fallback={<Spinner />}> <Settings /> </Suspense>

Advanced: React Server Components (Mental Model)

In modern frameworks (Next.js App Router), components are server-rendered by default and only "use client" when you opt in:

  • Server components — run on the server, can read the DB, can't use useState/useEffect. Output zero JS to the client.
  • Client components — what you've always written. Marked with "use client" at the top of the file.
The mental shift: most pages are server components, sprinkled with small interactive client islands (a search box, a toggle).

Advanced: Strict Mode Double-Render

(default in dev with most tooling) intentionally:

  • Calls your render function twice to surface impurities.
  • Mounts → unmounts → remounts each component once to surface broken cleanups.
  • Warns about deprecated APIs.
If something logs twice in dev but once in production, that's why — and that's the point.

Practice Path

1. Build a UserCard component that takes name, avatar, and bio props. 2. Render a list of 5 UserCards using map with proper keys. 3. Add a "Show bio" button per card that toggles the bio (you'll need state — see the next topic). 4. Refactor a hardcoded modal into a generic component using children.