React basics for 2026.

Function component

function Hello({ name }: { name: string }) {
  return <h1>Hello {name}</h1>;
}

<Hello name="World" />

Always start with function components. Class components are legacy.

JSX

const el = <div className="box" onClick={handle}>{text}</div>;

// Attributes use camelCase: className, htmlFor, tabIndex
// Curly braces for expressions
// Self-close: <img /> not <img>

Fragments

return (
  <>
    <h1>title</h1>
    <p>body</p>
  </>
);

// Or React.Fragment for keys
return items.map((it) => (
  <React.Fragment key={it.id}>
    <dt>{it.term}</dt>
    <dd>{it.def}</dd>
  </React.Fragment>
));

Conditional rendering

{cond && <Thing />}
{cond ? <A /> : <B />}
{cond && cond2 && <Thing />}

// Avoid number 0 leak:
{count > 0 && <Badge n={count} />}     // safe
{count && <Badge n={count} />}         // BAD: 0 renders "0"

Lists

{items.map((it) => (
  <li key={it.id}>{it.name}</li>
))}

Always provide key. Use stable IDs, not index (unless list is truly static).

Event handlers

<button onClick={() => doIt(id)}>click</button>
<form onSubmit={(e) => { e.preventDefault(); ... }}>
<input onChange={(e) => setVal(e.target.value)} />

useState

const [count, setCount] = useState(0);

setCount(count + 1);          // direct
setCount((c) => c + 1);       // updater form (preferred when based on prev)

Lazy initial state:

const [data, setData] = useState(() => expensiveInit());

useEffect

useEffect(() => {
  const id = setInterval(tick, 1000);
  return () => clearInterval(id);
}, [tick]);

Three forms:

  • [] — once after mount
  • [a, b] — when a or b changes
  • (no array) — after every render

Cleanup runs before next effect AND on unmount.

Controlled inputs

const [name, setName] = useState("");
<input value={name} onChange={(e) => setName(e.target.value)} />

Props

function Card({ title, children }: { title: string; children: React.ReactNode }) {
  return <div><h2>{title}</h2>{children}</div>;
}

<Card title="Hello">
  <p>Body</p>
</Card>

Spread props

<Button {...rest} />

// Pass through HTML attrs:
function Btn({ children, ...rest }: React.ComponentProps<"button">) {
  return <button {...rest}>{children}</button>;
}

Refs (uncontrolled)

const inputRef = useRef<HTMLInputElement>(null);

useEffect(() => { inputRef.current?.focus(); }, []);

<input ref={inputRef} />

Context

const ThemeContext = createContext<"light" | "dark">("light");

function App() {
  return (
    <ThemeContext.Provider value="dark">
      <Child />
    </ThemeContext.Provider>
  );
}

function Child() {
  const theme = useContext(ThemeContext);
  return <div>{theme}</div>;
}

Lifting state

When two siblings need shared state, move it to their parent and pass via props.

Composition over inheritance

function Modal({ children, onClose }: { children: React.ReactNode; onClose: () => void }) {
  return <div className="modal" onClick={onClose}>{children}</div>;
}

<Modal onClose={close}>
  <UserForm />
</Modal>

Strict Mode

<React.StrictMode>
  <App />
</React.StrictMode>

Double-invokes components in dev to surface impure renders. Keep enabled.

Keys gotcha

{items.map((it, i) => <li key={i}>{it}</li>)}    // BAD if list reorders
{items.map((it) => <li key={it.id}>{it.name}</li>)}  // GOOD

Reordering with index keys causes subtle state-bleed bugs.

Pure rendering

Components must be pure: same props → same output, no side effects during render.

// BAD
function Bad() {
  fetch("/x");          // side effect during render
  return <div />;
}

// GOOD
function Good() {
  useEffect(() => { fetch("/x"); }, []);
  return <div />;
}

Common mistakes

  • Mutating state directly — arr.push(x); setArr(arr) doesn’t re-render. Use setArr([...arr, x]).
  • Using index as key in reorderable list.
  • Setting state in render — infinite loop.
  • Forgetting deps array — runs every render.
  • useState callback — setCount(count + 1) twice in same tick only increments once.

Read this next

If you want my React + TS starter, it’s at rajpoot.dev .


Building something AI-, backend-, or data-heavy and want a second pair of eyes? I do consulting and freelance work — see my projects and ways to reach me at rajpoot.dev .