# React Fundamentals

## 1. What Problem React Solves

Before React, updating the DOM directly (`document.createElement`, `.appendChild`, `.innerHTML`) meant you had to track, by hand, exactly which nodes were stale and how to mutate them without breaking the rest of the page. That's manageable for a button but becomes unmanageable for an app with hundreds of interdependent UI states.

React's core idea: **you describe what the UI should look like for a given state, and React figures out how to make the real DOM match.** You never call `.appendChild` yourself. You write a function that returns a description of the UI, and React diffs that description against what's currently on screen.

```tsx
// Imperative (you manage every mutation)
const btn = document.createElement("button");
btn.textContent = "Count: 0";
let count = 0;
btn.addEventListener("click", () => {
  count++;
  btn.textContent = `Count: ${count}`; // YOU find and update this node
});
document.body.appendChild(btn);

// Declarative (React manages the mutation)
function Counter() {
  const [count, setCount] = useState(0);
  return <button onClick={() => setCount(count + 1)}>Count: {count}</button>;
}
```

In the declarative version you never touch the DOM. You describe the button for the current `count`, and call `setCount` when it should change. React re-runs `Counter`, gets a new description, and patches only the text node that actually changed.

## 2. JSX Is Syntactic Sugar

JSX (`<button>...</button>` inside a `.tsx` file) is **not** HTML and is **not** a runtime feature of JavaScript. It's compiled away entirely before your code ever runs — by the TypeScript compiler or Babel, depending on your toolchain.

```tsx
const element = <h1 className="title">Hello, {name}</h1>;
```

compiles to (modern "automatic" JSX runtime, React 17+):

```tsx
import { jsx as _jsx } from "react/jsx-runtime";
const element = _jsx("h1", { className: "title", children: `Hello, ${name}` });
```

`_jsx` (or the older `React.createElement`) is just a function call. JSX is purely a more readable way to write nested function calls — there is no special parser magic happening at runtime, only at build time.

## 3. React Elements Are Plain Objects

Calling `jsx(...)` (or `React.createElement(...)`) does **not** create a DOM node. It creates a plain, lightweight, serializable JavaScript object called a **React element**:

```tsx
// Roughly what <h1 className="title">Hello</h1> becomes at runtime:
{
  $$typeof: Symbol.for("react.element"),
  type: "h1",
  key: null,
  props: { className: "title", children: "Hello" },
}
```

This matters: elements are cheap to create and throw away. Every render of a component creates a brand-new tree of these plain objects — React never mutates an old element object, it always builds a fresh tree and compares it to the previous one (see the "Rendering and reconciliation" topic for exactly how that comparison works).

`type` can be a string (`"h1"`, `"div"` — a host/DOM element) or a function/class (your own component) or certain special symbols (`Fragment`, `Suspense`, etc.).

## 4. Components: Functions That Return Elements

A component is just a function that takes `props` and returns a React element tree (or `null`).

```tsx
type GreetingProps = { name: string };

function Greeting({ name }: GreetingProps) {
  return <p>Hello, {name}!</p>;
}

// Using it — this call also just produces a plain element object:
// { type: Greeting, props: { name: "Ana" } }
const el = <Greeting name="Ana" />;
```

Critically: `<Greeting name="Ana" />` does **not** call `Greeting()` immediately. It creates an element object with `type: Greeting`. React itself calls `Greeting(props)` later, during rendering, when it walks the tree.

## 5. Rendering to the DOM

The one place your app touches the real DOM directly is the entry point, where you mount the root:

```tsx
// main.tsx
import { createRoot } from "react-dom/client";
import App from "./App";

const container = document.getElementById("root")!;
const root = createRoot(container);
root.render(<App />);
```

`createRoot` creates a React root tied to one real DOM node. `root.render(<App />)` hands React an element tree; from that point forward, React owns everything inside `container` — it decides which real DOM nodes to create, update, or remove, and you never call DOM APIs on that subtree yourself again.

## 6. Function Components vs Class Components

Modern React code is almost entirely function components with hooks. Class components still work (React has no plans to remove them) but are considered legacy for new code:

```tsx
// Function component (current standard)
function Welcome({ name }: { name: string }) {
  return <h1>Welcome, {name}</h1>;
}

// Class component (legacy, still supported)
class WelcomeClass extends React.Component<{ name: string }> {
  render() {
    return <h1>Welcome, {this.props.name}</h1>;
  }
}
```

Both produce the identical kind of output (a React element tree). The difference is entirely in how they hold local state and hook into lifecycle — covered in the "State" and "Component lifecycle" topics.

## 7. Under the Hood: From JSX to Pixels

### Compile time: JSX becomes function calls

Your build tool (esbuild/SWC in Vite, or Babel in CRA) transforms every JSX tag into a `jsx(type, props, key)` call before the browser or Node ever sees your code. TypeScript itself can do this transform too when `jsx: "react-jsx"` is set in `tsconfig.json` — it's not React-specific magic, it's a compiler transform target that any tool can implement.

### First render time: elements become a Fiber tree

When `root.render(<App />)` runs, React doesn't just recurse through your element tree and produce DOM nodes directly. It builds a parallel data structure called the **fiber tree** — one **fiber** (a plain JS object) per component/host element, forming a linked structure (`child`, `sibling`, `return` pointers — not an array of children) that mirrors your element tree but persists across renders and carries bookkeeping React needs (`memoizedState`, `memoizedProps`, `flags`, etc). Fibers are the actual unit of work React's reconciler processes; elements are just the ephemeral, disposable description each render produces.

```
<App>                         Fiber tree (persists across renders)
  <Header/>          ─────►   FiberRoot
  <Main>                        └─ App fiber
    <Counter/>                      ├─ Header fiber
  </Main>                           └─ Main fiber
</App>                                   └─ Counter fiber
```

### The two phases: render and commit

React processes work in two distinct phases:

1. **Render phase** — React calls your component functions, builds/updates the fiber tree, and computes what changed. This phase can be paused, thrown away, or redone (React uses this for concurrent features like time-slicing) because it has **no visible side effects** — nothing touches the real DOM yet.
2. **Commit phase** — React walks the fiber tree's recorded effects and applies them to the real DOM in one synchronous pass: inserting, updating, and removing actual nodes, then running layout effects and (asynchronously, after paint) passive effects (`useEffect`). This phase is **not interruptible** — once it starts, it runs to completion, because a half-applied DOM mutation would leave the screen in a broken state.

This two-phase split is the mechanical reason your component function body must stay pure (no DOM mutation, no side effects) — it can run multiple times, or be discarded, before anything ever reaches the screen. Only code inside `useEffect`/`useLayoutEffect` is guaranteed to run exactly once per actual commit.

![JSX compiles to element objects, which the reconciler turns into a persistent fiber tree, processed in a render phase then applied in a commit phase](diagrams/01-jsx-to-fiber-pipeline.svg)

## 8. Common Pitfalls

1. **Treating JSX as HTML** — attributes are camelCase (`className`, `onClick`, `htmlFor`), and every tag must close (`<img />`, not `<img>`). It's JavaScript, not markup.
2. **Assuming `<Component />` calls the function immediately** — it only builds an element object; React decides when (and whether) to actually invoke your function.
3. **Mutating the DOM directly alongside React** (e.g. `document.querySelector(...).style.color = "red"` inside a component body) — React doesn't know about that change, so the next render can silently overwrite or conflict with it.
4. **Forgetting a component must return a single root** — return a `Fragment` (`<>...</>`) or array, not multiple sibling elements with no wrapper.
5. **Putting side effects (network calls, subscriptions) directly in the component body** — the render phase can run more than once per commit (React may call your function again to recompute) or be thrown away, so anything with a real-world effect belongs in `useEffect`, not in the function body itself.

## 9. Quick Reference

| Concept | What it actually is |
|---|---|
| JSX | Compile-time syntax sugar for `jsx()`/`createElement()` calls |
| React element | A plain, immutable JS object describing what to render (`{ type, props }`) |
| Component | A function that takes props and returns elements |
| Fiber | A persistent JS object per component/host node; the reconciler's real unit of work |
| Render phase | Calls components, builds/diffs fiber tree — pure, interruptible, no DOM writes |
| Commit phase | Applies DOM mutations, runs layout/passive effects — synchronous, not interruptible |
| `createRoot(...).render(<App />)` | The one place your code hands React ownership of a real DOM subtree |
