# React Cheatsheet

Components, JSX, hooks, and routing — the React surface we cover in L8 and Lab 4.

## Project setup

```bash
npm create vite@latest my-app -- --template react
cd my-app
npm install
npm run dev
```

## Functional component

```jsx
function Greeting({ name = "world" }) {
  return <h1>Hello, {name}!</h1>;
}

export default Greeting;
```

## JSX rules

- Return **one** root element (or a `<>...</>` Fragment).
- `className` not `class`; `htmlFor` not `for`.
- Use `{}` to embed JS expressions: `{user.name}`, `{1 + 2}`.
- Conditional render: `{isOpen && <Modal/>}` or `{ok ? <A/> : <B/>}`.
- Lists need a stable `key`: `items.map(it => <li key={it.id}>{it.name}</li>)`.

## Props & children

```jsx
function Card({ title, children }) {
  return (
    <article>
      <h3>{title}</h3>
      {children}
    </article>
  );
}

<Card title="Hi"><p>Body</p></Card>
```

## useState

```jsx
import { useState } from "react";

function Counter() {
  const [count, setCount] = useState(0);
  return (
    <button onClick={() => setCount(c => c + 1)}>
      Clicked {count} times
    </button>
  );
}
```

State updates are **async** and **immutable**:
```jsx
setUser({ ...user, name: "New" });           // ✓ new object
setItems([...items, newItem]);               // ✓ new array
// ✗ user.name = "New"   — never mutate
```

## useEffect

```jsx
import { useEffect, useState } from "react";

function Users() {
  const [users, setUsers] = useState([]);

  useEffect(() => {
    let cancelled = false;
    fetch("/api/users")
      .then(r => r.json())
      .then(data => { if (!cancelled) setUsers(data); });
    return () => { cancelled = true; };       // cleanup
  }, []);                                       // [] = run once on mount

  return <ul>{users.map(u => <li key={u.id}>{u.name}</li>)}</ul>;
}
```

Dependency arrays:
- `[]` — run once after mount.
- `[id]` — run when `id` changes.
- omitted — run after **every** render (rarely what you want).

## Forms

```jsx
function LoginForm() {
  const [email, setEmail] = useState("");

  const submit = (e) => {
    e.preventDefault();
    console.log({ email });
  };

  return (
    <form onSubmit={submit}>
      <input
        type="email"
        value={email}
        onChange={e => setEmail(e.target.value)}
      />
      <button>Sign in</button>
    </form>
  );
}
```

## Lifting state up

```jsx
function App() {
  const [filter, setFilter] = useState("");
  return (
    <>
      <SearchBar value={filter} onChange={setFilter} />
      <Results query={filter} />
    </>
  );
}
```

## Routing — react-router

```bash
npm install react-router-dom
```

```jsx
import { BrowserRouter, Routes, Route, Link, useParams } from "react-router-dom";

function App() {
  return (
    <BrowserRouter>
      <nav>
        <Link to="/">Home</Link> · <Link to="/about">About</Link>
      </nav>
      <Routes>
        <Route path="/" element={<Home/>} />
        <Route path="/courses/:id" element={<Course/>} />
        <Route path="*" element={<NotFound/>} />
      </Routes>
    </BrowserRouter>
  );
}

function Course() {
  const { id } = useParams();
  return <h2>Course {id}</h2>;
}
```

## Other built-in hooks

```jsx
useRef(initial)         // mutable ref that doesn't cause re-render
useMemo(() => f(x), [x])     // cache expensive computation
useCallback(fn, [deps]) // cache function identity
useContext(MyContext)   // read context value
useReducer(reducer, init)    // alternative to useState for complex state
```

## Custom hooks

```jsx
function useFetch(url) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  useEffect(() => {
    setLoading(true);
    fetch(url).then(r => r.json()).then(d => {
      setData(d); setLoading(false);
    });
  }, [url]);
  return { data, loading };
}
```

Convention: hooks start with `use`.

## Common mistakes

- Mutating state directly (`arr.push(x)` then `setArr(arr)`).
- Forgetting `key` on list items, or using array index as key.
- Calling hooks inside conditions/loops — they must be at the top of the component.
- Missing dependencies in `useEffect` — install ESLint plugin `react-hooks` to catch this.
- Calling state setters during render (causes infinite loop).

## Tools & references

- React docs (new): <https://react.dev/>
- React Router docs: <https://reactrouter.com/>
- React DevTools (browser extension): <https://react.dev/learn/react-developer-tools>
- Vite: <https://vitejs.dev/>
