let x=>.map()<div>color: teal____________
Theebug — Learn to Code by Doing
Start Learning
docs.md
THEEBUGdocs.md

React Reference

Components, props, state, and the hooks that power modern React apps.

/** JSX Syntax */

JSX lets you write markup that looks like HTML directly inside JavaScript: const el = <h1>Hello!</h1>. Under the hood, a build tool (Babel, or Next.js's compiler) transforms it into plain JavaScript function calls — JSX is a convenience, not something browsers understand natively.

Curly braces {} embed a real JavaScript expression inside JSX — {name}, {1 + 1}, {items.length} all work, since each is a single expression that evaluates to a value. A full statement (if, for, a variable declaration) can't go directly inside {} — JSX only accepts expressions.

Every JSX element must have exactly one root/outermost element — two sibling elements at the top level is a compile error. When there's no single natural wrapper, a Fragment (<>...</>) groups multiple elements without adding an extra DOM node.

Embedding an expression
const name = "Ada";
const el = <h1>Hello, {name}!</h1>;
Grouping siblings with a Fragment
return (
  <>
    <h1>Title</h1>
    <p>Body text</p>
  </>
);
className, not class — since class is a reserved word in JavaScript, JSX uses className for the HTML class attribute. It's one of the most common "why isn't my style applying" mistakes when coming from plain HTML.

/** Components & Props */

A component is just a function that returns JSX, named starting with a capital letter (Welcome, not welcome) — that capitalization is exactly how React and JSX tell your custom components apart from built-in HTML tags like <div>.

Props are how a parent passes data into a child: <Welcome name="Ada" /> passes { name: "Ada" } as a single object, which the component receives as its one function argument — destructuring it in the parameter list ({ name }) is the common, readable way to read specific props.

Props flow one direction only, parent to child — a component can read the props it was given, but can never reassign or modify them. If a value needs to change over time, that's what state (next section) is for, not props.

A component reading props via destructuring
function Badge({ label, color }) {
  return <span style={{ color }}>{label}</span>;
}
Passing props from a parent
<Badge label="New" color="teal" />
children is a special, automatically-passed prop containing whatever was written between a component's opening and closing tags — <Card><p>Hi</p></Card> gives Card a children prop equal to that <p> element.

/** State with useState */

useState gives a component a piece of memory that survives across re-renders — const [count, setCount] = useState(0) returns a pair: the current value, and a function to update it. Both names are yours to choose; only the pairing and order (value, then setter) is fixed.

Calling the setter doesn't just update a plain variable — it tells React to re-render the component with the new value. A component's regular local variables reset to their initial expression on every render; state is specifically what persists between them.

The value passed to useState(...) is only used once — the very first time the component renders. After that, the state's current value is whatever it was most recently set to, completely independent of that initial argument.

A boolean toggle
const [isOpen, setIsOpen] = useState(false);
setIsOpen(!isOpen);
Updating from the previous value safely
setCount((prev) => prev + 1);
When a new state value depends on the previous one, pass a function to the setter (setCount(prev => prev + 1)) instead of reading the outer variable directly — it avoids a real, if subtle, stale-value bug when multiple updates happen in quick succession.

/** Event Handling */

React event handler props are camelCase, not lowercase: onClick, onChange, onSubmit — the plain lowercase HTML versions (onclick) simply do nothing in JSX, since React defines its own consistent naming for every event.

A handler prop always takes a function, never the result of calling one — onClick={() => setCount(count + 1)} passes a function to run *later*, on click. Writing onClick={setCount(count + 1)} instead calls it immediately during render, a very common early mistake.

The event object React passes to a handler (onChange={(e) => ...}) is a SyntheticEvent — a cross-browser wrapper around the native browser event, normalized so the same code behaves consistently regardless of which browser is running it.

A click handler with an argument
<button onClick={() => setCount(count + 1)}>+1</button>
Reading input as the user types
<input onChange={(e) => setText(e.target.value)} />
A handler that doesn't need an argument can be passed directly without an arrow-function wrapper: onClick={handleClick} — only wrap it in () => ... when you need to pass a specific argument or run more than one statement.

/** Conditional Rendering */

JSX can only contain expressions, not statements — an if/else block doesn't evaluate to a value, so it can't be dropped directly inside {}. A ternary (condition ? a : b) does evaluate to a value, making it the standard way to choose between two outputs inline.

For an all-or-nothing case — show something, or show nothing — {condition && <Component />} is the more common shorthand: && short-circuits to render nothing at all when condition is false, with no separate else branch needed.

A well-known && gotcha: {count && <p>{count} items</p>} renders a literal 0 on screen when count is exactly 0, since 0 is falsy but is still what && returns. Writing {count > 0 && ...} (an actual boolean) avoids it.

Ternary for two possible outputs
{isOnline ? "Online" : "Offline"}
&& for show-or-nothing
{unreadCount > 0 && <Badge count={unreadCount} />}
If a conditional starts nesting more than one level deep inside JSX, it's usually clearer to compute the result in a variable *before* the return statement, then reference that variable in the JSX — rather than cramming the logic inline.

/** Rendering Lists & Keys */

Array.map() is the standard way to turn a list of data into a list of elements: {items.map((item) => <li key={item.id}>{item.text}</li>)} — the same .map() from plain JavaScript, just returning JSX instead of plain values.

key is a special prop, read only by React itself (never passed down to your actual component), that lets React track which rendered item is which across re-renders — without a stable key, React falls back to comparing by position, which can misattribute state after an insertion, deletion, or reorder.

key must be unique only among *sibling* elements in that specific list, not globally unique across the whole app — two unrelated lists elsewhere on the page can safely reuse the same key values with no conflict.

Mapping data to list items with a stable key
const todos = [{ id: 1, text: "Milk" }, { id: 2, text: "Eggs" }];
todos.map((t) => <li key={t.id}>{t.text}</li>);
Using the array index as a key (items.map((item, i) => <li key={i}>...)) silences React's console warning and often *looks* fine — but it breaks exactly in the case key exists to solve (reordering or inserting items), since the index doesn't actually identify the item.

/** useEffect & Side Effects */

useEffect runs code *after* a render commits to the screen — for anything that reaches outside React's own rendering, like fetching data, subscribing to an event, or manually working with a DOM API. useEffect(() => { ... }, [deps]) takes a function to run and a dependency array controlling when it re-runs.

The dependency array is the part that trips people up most: [] (empty) means "run once, after the first render only"; [count] means "re-run whenever count changes"; omitting the array entirely means "run after every single render," almost never what you actually want.

Returning a function from inside the effect defines cleanup — React calls it right before the effect re-runs, and once more when the component is removed entirely. This is how you unsubscribe from something you subscribed to, preventing a real memory leak.

Running once on mount
useEffect(() => {
  console.log("mounted");
}, []);
Subscribing with cleanup
useEffect(() => {
  const id = setInterval(tick, 1000);
  return () => clearInterval(id);
}, []);
A missing or wrong dependency array is one of the most common sources of real React bugs — either an effect that never updates when it should (missing a dependency), or one that runs far more often than intended (an empty array left off by accident).

/** Forms & Controlled Inputs */

A "controlled" input has its value driven entirely by React state, not by the DOM itself: <input value={text} onChange={(e) => setText(e.target.value)} /> — every keystroke updates state, and state is what determines what the input displays, keeping React as the single source of truth.

Without the onChange handler, a controlled input (one with a value prop) becomes read-only — React will keep resetting the displayed value back to whatever's in state, ignoring what the user actually typed, since there's nothing telling state to update.

checkboxes use checked instead of value (checked={isAgreed}, with an onChange to flip it), and a <select> uses value on the <select> element itself rather than a selected attribute on the individual <option>s — small but real differences from plain HTML forms.

A fully controlled text input
const [text, setText] = useState("");
<input value={text} onChange={(e) => setText(e.target.value)} />
A controlled checkbox
<input type="checkbox" checked={isAgreed} onChange={(e) => setIsAgreed(e.target.checked)} />
A checkbox reads e.target.checked, not e.target.value, in its onChange handler — using .value on a checkbox is a common copy-paste mistake from a regular text input.

/** Composing Components */

Real React apps are built by composing many small components together, not one giant component — a Page might render a Header, a List of Card components, and a Footer, each handling its own small piece of the UI.

When two sibling components both need access to the same changing value, the fix is "lifting state up": move the useState call to their closest common parent, then pass the value and its setter down as props to both children — rather than trying to have one child talk directly to another.

The children prop (mentioned in Components & Props) is what makes generic wrapper components possible — a Card component can render <div className="card">{children}</div> and work with any content placed between its tags, without knowing in advance what that content will be.

Lifting state up to a shared parent
function Parent() {
  const [value, setValue] = useState("");
  return (
    <>
      <Input value={value} onChange={setValue} />
      <Preview value={value} />
    </>
  );
}
If you find yourself passing the same prop down through three or four layers of components that don't actually use it themselves (just to reach a component further down), that's a common sign it might be worth reaching for Context instead — a way to make a value available to a whole subtree without manually threading it through every level.

/** Custom Hooks */

A custom hook is just a regular JavaScript function whose name starts with use, that itself calls other hooks (useState, useEffect, etc.) inside it — a way to extract and reuse stateful logic between components, without repeating the same useState/useEffect pair everywhere it's needed.

The use prefix isn't just convention for readability — React's own tooling (and the linter rule that ships with React) uses it to know which functions need to follow the Rules of Hooks (like never calling a hook conditionally), so skipping the prefix on a function that calls hooks internally will cause real, hard-to-diagnose lint gaps.

A custom hook returns whatever the component calling it needs — often an array like useState's own [value, setter] pattern, or an object with several named values — and every component that calls it gets its own, completely independent copy of that state.

A reusable toggle hook
function useToggle(initial = false) {
  const [value, setValue] = useState(initial);
  const toggle = () => setValue((v) => !v);
  return [value, toggle];
}
A custom hook doesn't share state between the components that call it — each call to useToggle() in the example gets its own independent value, the same way each call to useState() does. A hook shares reusable *logic*, not the state's actual data.
main
Markdown