# React, TypeScript & JavaScript — A Deep Dive --- ## Part 1: JavaScript Fundamentals ### Everything is an Object JavaScript has one foundational truth: **everything is an object**, or behaves like one. Numbers, strings, functions, arrays, classes — they all ultimately descend from `Object`. ```js typeof {} // "object" typeof [] // "object" typeof function () {} // "function" (but instanceof Object === true) typeof 42 // "number" (primitive, but auto-boxed to Number object) ``` Primitives (`string`, `number`, `boolean`, `null`, `undefined`, `symbol`, `bigint`) are the exception — they're not objects — but JavaScript automatically "boxes" them into their object wrappers when you access properties on them: ```js 'hello'.toUpperCase() // JS temporarily wraps "hello" in a String object ``` --- ### Functions Are Objects Functions in JS are **first-class objects** — they can be assigned to variables, passed as arguments, and have properties attached to them. ```js function greet() { return 'hello' } greet instanceof Function // true greet instanceof Object // true // Functions can have properties like any object greet.version = '1.0' console.log(greet.version) // "1.0" ``` This is why you can pass functions as callbacks, store them in arrays, and return them from other functions. It's also why React can accept both function components and class components — they're both just callable objects. --- ### Classes Are Just Functions `class` syntax in JavaScript is **syntactic sugar** over constructor functions and prototypes. Under the hood, they compile down to the same thing. ```js // Modern class syntax: class Dog { constructor(name) { this.name = name } bark() { console.log('woof') } } // Is identical to this older style: function Dog(name) { this.name = name } Dog.prototype.bark = function () { console.log('woof') } // Proof: typeof Dog // "function" — classes ARE functions ``` The `prototype` chain is how JavaScript does inheritance — when you call `dog.bark()`, JS looks up the chain: instance → `Dog.prototype` → `Object.prototype`. --- ### `this` — The Most Confusing Part of JS `this` refers to the object that **called** the function, not where the function was defined. This causes bugs when passing methods as callbacks. ```js class Timer { constructor() { this.count = 0 } tick() { this.count++ } // `this` works fine here } const t = new Timer() setTimeout(t.tick, 1000) // ❌ `this` is undefined — tick lost its context setTimeout(() => t.tick(), 1000) // ✅ arrow function preserves `this` ``` **Arrow functions** don't have their own `this` — they inherit it from the surrounding scope. This is why they're preferred for callbacks and class methods in React. --- ### The Event Loop JavaScript is **single-threaded** — it can only do one thing at a time. The event loop is how it handles async operations without blocking: ``` Call Stack → runs sync code ↓ Web APIs → handles async (setTimeout, fetch, etc.) ↓ Callback Queue → waits for stack to be empty ↓ Event Loop → moves callbacks back to stack when ready ``` ```js console.log('1') setTimeout(() => console.log('2'), 0) // async — goes to queue console.log('3') // Output: 1, 3, 2 // Even with 0ms delay, setTimeout is async and waits for stack to clear ``` --- ### Async / Await and Promises `async/await` is syntactic sugar over Promises. A `Promise` represents a value that will be available in the future. ```js // Promise style: fetch('/api/user') .then((res) => res.json()) .then((data) => console.log(data)) .catch((err) => console.error(err)) // Async/await style (same thing, cleaner): async function getUser() { try { const res = await fetch('/api/user') const data = await res.json() console.log(data) } catch (err) { console.error(err) } } ``` `async` functions always return a Promise, even if you return a plain value. --- ### Arrow Functions vs Function Declarations ```js // Function declaration — hoisted, has own `this` function getUser() {} getUser() // ✅ callable before definition // Arrow function — not hoisted, inherits `this` const getUser = () => {} getUser() // ❌ ReferenceError if called before declaration ``` For React components and utility functions the two are functionally equivalent — the choice is mostly style. Arrow functions are preferred for callbacks; function declarations are conventional for top-level utilities and Next.js exports. --- ## Part 2: TypeScript TypeScript is JavaScript with a **type system layered on top**. It compiles down to plain JavaScript — the browser never sees TypeScript. --- ### What TypeScript Adds ```ts // JavaScript — no safety function add(a, b) { return a + b } add('hello', 42) // runs, returns "hello42" — probably a bug // TypeScript — caught at compile time function add(a: number, b: number): number { return a + b } add('hello', 42) // ❌ Error: Argument of type 'string' is not assignable to 'number' ``` TypeScript catches bugs before runtime, makes refactoring safer, and provides autocomplete in editors. --- ### `interface` vs `type` Both describe the shape of an object, but they have key differences: ```ts // interface — extendable, mergeable, best for object shapes interface User { name: string age: number } interface Admin extends User { role: string } // Declaration merging — only interfaces can do this interface User { email: string } // User now has: name, age, email ✅ // type — more flexible, supports unions, tuples, primitives type ID = string | number // union — impossible with interface type Pair = [string, number] // tuple — impossible with interface type User = {name: string} // object shape — works like interface // type uses intersection instead of extends: type Admin = User & {role: string} // type CANNOT be merged: type User = {email: string} // ❌ Duplicate identifier error ``` **Rule of thumb:** Use `interface` for component props and object shapes; use `type` for unions, tuples, or complex compositions. --- ### Generics Generics let you write reusable code that works with multiple types while remaining type-safe: ```ts // Without generics — loses type info function first(arr: any[]): any { return arr[0] } // With generics — type is preserved function first(arr: T[]): T { return arr[0] } const num = first([1, 2, 3]) // TypeScript knows: num is number const str = first(['a', 'b']) // TypeScript knows: str is string ``` --- ### Utility Types TypeScript ships with built-in type transformers: ```ts interface User { name: string age: number email: string } Partial // all fields optional Required // all fields required Pick // only { name: string } Omit // everything except email Readonly // all fields immutable Record // { [key: string]: User } ``` These are heavily used in React for prop types — e.g., `Partial` for a component where all props are optional. --- ## Part 3: React React is a **UI library** built on one core idea: your UI is a function of your state. ``` UI = f(state) ``` When state changes, React re-runs your component function and figures out the minimal DOM updates needed. --- ### What React Actually Does React never touches the real DOM directly. It maintains a **Virtual DOM** — a lightweight JavaScript object tree representing the UI. When state changes: 1. React re-renders the component (calls the function again) 2. Compares new Virtual DOM to previous (called **diffing** or **reconciliation**) 3. Applies only the minimal changes to the real DOM (**patching**) This is fast because DOM operations are expensive; JS object comparisons are cheap. --- ### JSX JSX looks like HTML in JavaScript but it's neither — it's **syntactic sugar** for `React.createElement()` calls: ```jsx // What you write: const el =
Hello
// What it compiles to: const el = React.createElement("div", {className: "box"}, "Hello") // Which produces a plain JS object: { type: "div", props : { className: "box", children : "Hello" } } ``` React reads these objects to build and update the DOM. --- ### Components — The Building Block A component is any function that returns JSX. React identifies components by their capital letter. ```tsx // Function component (modern standard) function Button({label, onClick}: {label: string; onClick: () => void}) { return } // Class component (legacy) class Button extends React.Component<{label: string}> { render() { return } } ``` **Why both work:** React calls `Component(props)` for function components and `new Component(props).render()` for class components. Both return JSX objects, which is all React needs. Since JavaScript classes are just functions with prototypes, they're both "callable things that return JSX" at the engine level. --- ### The Component Lifecycle Every component goes through: **mount → update → unmount** ``` Mount → component appears in the DOM Update → state or props change, component re-renders Unmount → component is removed from the DOM ``` In function components, `useEffect` handles all lifecycle stages: ```tsx useEffect(() => { // Runs after mount (and after updates if deps change) const subscription = subscribe() return () => { // Cleanup — runs before unmount (or before next effect) subscription.unsubscribe() } }, [dependency]) // runs again whenever `dependency` changes // [] = run once on mount only // no array = run after every render ``` --- ### Props vs State ```tsx // Props — data passed IN from a parent. Read-only. function Greeting({name}: {name: string}) { return

Hello, {name}

} // State — data owned BY the component. Triggers re-render when changed. function Counter() { const [count, setCount] = useState(0) return } ``` The key distinction: **props flow down** (parent → child), **state lives inside** the component. --- ### Hooks Hooks are a **special category of function** — not a component, not a plain method. They let function components access React features like state and lifecycle. They have strict rules: only call them at the top level of a component (not inside conditions or loops), and only inside React functions. ```tsx useState() // local component state useEffect() // side effects & lifecycle useRef() // reference a DOM element or persist a value without re-render useContext() // consume a React Context useMemo() // memoize an expensive calculation useCallback() // memoize a function reference useReducer() // complex state logic (like a mini Redux) ``` **Custom hooks** let you extract and reuse stateful logic: ```tsx function useWindowWidth() { const [width, setWidth] = useState(window.innerWidth) useEffect(() => { const handler = () => setWidth(window.innerWidth) window.addEventListener('resize', handler) return () => window.removeEventListener('resize', handler) }, []) return width } // Reusable in any component: function Layout() { const width = useWindowWidth() return
{width > 768 ? : null}
} ``` --- ### Context — Avoiding Prop Drilling Passing props through many layers of components is called **prop drilling**. Context solves it by broadcasting data to any component in the tree. ```tsx // Create context const ThemeContext = createContext<'light' | 'dark'>('light') // Provide it high in the tree function App() { return ( ) } // Consume it anywhere below — no props needed function Button() { const theme = useContext(ThemeContext) return } ``` --- ### React's Different "Types" of Things | Type | Returns | Naming | Purpose | | -------------------- | ---------------- | --------------- | ----------------------------- | | **Component** | JSX | Capitalized | UI building block | | **Hook** | Data / functions | `use` prefix | Stateful logic | | **Event Handler** | void / anything | `handle` prefix | Responds to events | | **Utility Function** | Anything | Anything | Pure logic, no React rules | | **HOC** | A component | `with` prefix | Wraps and enhances components | | **Custom Hook** | Data / functions | `use` prefix | Reusable stateful logic | | **Context** | — | — | Cross-tree data sharing | | **Ref** | Mutable object | — | DOM access / stable values | | **Portal** | — | — | Render outside DOM tree | --- ### A Complete Component in Context ```tsx // Types interface ProfileProps { profile: Profile label: string // a prop, not a second parameter } // Component export function ProfilePersonality({profile, label}: ProfileProps) { // Hook — stateful logic const [isExpanded, setIsExpanded] = useState(false) // Derived value — plain calculation, not a hook const mbtiType = label + '-MBTI' // Effect — side effect (lifecycle) useEffect(() => { document.title = `Profile: ${profile.name}` return () => { document.title = 'App' } }, [profile.name]) // Event handler const handleToggle = () => setIsExpanded((prev) => !prev) // JSX — the UI return (
{mbtiType && {mbtiType}}
) } ``` --- ## The Big Picture ``` JavaScript ├── Everything is an object (or behaves like one) ├── Functions are first-class objects ├── Classes are functions with prototype chains └── Async model: single-threaded + event loop ↓ adds TypeScript ├── Static type checking at compile time ├── interfaces & types for describing shapes ├── Generics for reusable type-safe code └── Compiles away — browser sees plain JS ↓ builds React ├── UI = f(state) — components are functions of their data ├── Virtual DOM + diffing = efficient real DOM updates ├── JSX compiles to React.createElement() calls ├── Hooks give functions lifecycle + state (no class needed) └── Props flow down, state lives inside, context broadcasts ``` The layering is intentional: TypeScript makes JavaScript safer; React gives JavaScript a model for building reactive UIs. Understanding JS fundamentals (objects, functions, `this`, async) makes React's behaviour — re-renders, closures in hooks, stale state bugs — much more predictable.