← React, from components to interview-ready

Lesson 1 of 5

How React thinks: components, JSX and the render cycle

4 min read

React is a library for building user interfaces out of components: functions that take data (props) and return a description of what the screen should look like. You never tell the browser "add this div, then change that text". You describe the UI for the current data, and React works out the smallest set of DOM changes to get there.

Components are just functions

jsx
function Greeting({ name }) {
  return <h1>Hello, {name}</h1>;
}

export default function App() {
  return (
    <main>
      <Greeting name="Asha" />
      <Greeting name="Rahul" />
    </main>
  );
}

Three rules worth saying out loud in an interview:

  • A component name starts with a capital letter. <greeting /> would be treated as an HTML tag.
  • A component must return one root element. Use a fragment <>...</> when you don't want an extra div.
  • A component should be pure while rendering: same props and state in, same JSX out, no side effects (no API calls, no changing variables outside the function). Side effects belong in event handlers or effects.

What JSX really is

JSX is syntax sugar. The compiler turns it into function calls:

jsx
const el = <button className="primary" onClick={save}>Save</button>;
// becomes roughly
const el = React.createElement("button", { className: "primary", onClick: save }, "Save");

That is why you write className (not class), why you can embed any JavaScript expression inside {} but not statements like if or for, and why JSX values can be stored in variables, passed as props and returned from functions.

Conditional rendering and lists are just JavaScript:

jsx
function Cart({ items }) {
  if (items.length === 0) return <p>Your cart is empty.</p>;
  return (
    <ul>
      {items.map((item) => (
        <li key={item.id}>
          {item.name} {item.qty > 1 && <span>× {item.qty}</span>}
        </li>
      ))}
    </ul>
  );
}

Watch out: {count && <Badge />} renders a literal 0 when count is 0. Use {count > 0 && <Badge />}.

Props flow down, events flow up

Props are read-only inputs passed from parent to child. A child never edits its props; to change something, the parent passes down a function and the child calls it.

jsx
function Counter({ value, onIncrement }) {
  return <button onClick={onIncrement}>Clicked {value} times</button>;
}

function Parent() {
  const [count, setCount] = useState(0);
  return <Counter value={count} onIncrement={() => setCount(count + 1)} />;
}

This one-way data flow is what makes React apps predictable: to find out why something shows on screen, follow the props up to whoever owns the state.

The render cycle

  1. Trigger: the first mount, or a state update (setState), or a parent re-rendering.
  2. Render: React calls your component functions to get the new JSX tree. Nothing touches the DOM yet.
  3. Reconcile: React compares the new tree with the previous one (the "virtual DOM diff").
  4. Commit: React applies only the differences to the real DOM, then runs effects.

Key fact interviewers love: when a component re-renders, all of its children re-render too by default, whether or not their props changed. That is usually fine, because rendering is cheap and the DOM is only touched where something actually changed. You optimise only when you measure a real problem (covered in the performance lesson).

Keys and reconciliation

When React diffs a list, it uses key to match old items to new ones. With stable keys (database ids), React can move, insert or delete items correctly. With array indexes as keys, inserting at the top shifts every index, so React may reuse the wrong component and its state ends up on the wrong row (a classic bug with input fields in lists).

  • Use a stable, unique id from your data.
  • Index keys are acceptable only for static lists that never reorder or filter.
  • Changing a component's key on purpose is a neat trick to reset its state (for example <ProfileForm key={userId} />).

Check yourself

  • Why must components be pure during render?
  • What does JSX compile to, and why can't you put an if statement inside {}?
  • What happens to child components when a parent's state changes?
  • Why is using the array index as a key risky?

Sign up free to save your progress.