0 / 91
Week 9 · Day 57 of 91

React project and component model

React Frontend Fundamentals

Objective

Create a React TypeScript app and understand what React adds.

A React component is a reusable functional block with inputs (props), internal state, and rendered output.

  • components as functions
  • JSX
  • render tree

Why this matters

On Day 25 and Day 26 you built pages by hand: document.querySelector, createElement, textContent = ..., appendChild. It worked, but every screen update was a list of instructions you had to keep in sync with reality. Today you meet React, which flips that around: you write a function that describes what the page should look like for the current data, and React works out which DOM operations get you there.

By the end of the hour you will have a running React TypeScript project and a dashboard split into three components that you can name, point at, and explain.

What React actually changes

Here is the Day 26 way of showing an equipment count, written out honestly:

const el = document.querySelector("#count");
el.textContent = `${items.length} items`;
if (items.length === 0) {
  el.classList.add("empty");
} else {
  el.classList.remove("empty");
}

Notice the shape: you tell the browser how to get from the old screen to the new screen, step by step. That is called imperative code, and it has a specific failure mode — add a new way for items to change, forget one of these lines, and the screen now disagrees with the data.

React is declarative. You write one function that answers a single question: given this data, what should be on screen?

function Count({ items }: { items: Equipment[] }) {
  return <p className={items.length === 0 ? "empty" : ""}>{items.length} items</p>;
}

There is no "add class" and no "remove class". There is one description, and React makes the real DOM match it. When the data changes, React runs the function again, compares the new description with the previous one, and applies only the differences to the real DOM.

Combinational logic instead of a sequence of switch throws

Imperative DOM code is an operator flipping switches in order to move a panel from one state to another — get the order wrong and the panel lies. A React component is a combinational block: you specify the output for each input condition, and the block settles to that output whenever the inputs change. You describe the truth table, not the switching sequence.

Components are functions that return UI

A component is a reusable unit of user interface, and in modern React it is written as a plain JavaScript function. That is the whole definition. It takes data in, and it returns a description of what to show.

function Header() {
  return <h1>Equipment Dashboard</h1>;
}

Two rules the tooling enforces:

  1. The name must start with a capital letter. Header is a component; header is treated as the HTML <header> tag. This is not a style preference — it is how React tells them apart.
  2. It returns UI, and it does so without touching anything outside itself. Same input, same output, no surprise side effects. Day 61 covers the escape hatch for when you genuinely need one.

You use a component by writing it as a tag: <Header />. Data goes in through attributes, called props, which arrive as a single object parameter:

function SummaryCard({ label, value }: { label: string; value: number }) {
  return (
    <article className="card">
      <h2>{label}</h2>
      <p>{value}</p>
    </article>
  );
}

// used as:  <SummaryCard label="Total units" value={42} />

{ label, value } is object destructuring, from Day 20, and the annotation after the colon is Week 5 TypeScript applied to the props object. Day 58 goes deeper; today, see that props are function arguments with a different spelling.

A functional block with labelled inputs

This is the week's core picture. A component is a block on a schematic: it has labelled inputs (props), it may hold some internal state, and it produces a defined output (the rendered UI). You can drop the same block into three places in a design with different input values and get three correct, independent instances. You do not re-derive the block each time.

JSX is syntax, not magic

<h1>Equipment Dashboard</h1> inside a .tsx file is JSX — an extension to JavaScript syntax. It is not a string, and it is not HTML. Before your code runs, the build tool (Vite, from Day 30) compiles every JSX tag into an ordinary function call that returns a plain JavaScript object.

const element = <h1 className="title">Pump 3</h1>;

console.log(element.type);  // "h1"
console.log(element.props); // { className: 'title', children: 'Pump 3' }

That object is a React element: a description of something to render, not the thing itself. Nothing has touched the DOM at that point. JSX is a shorter way to build a tree of objects.

Because JSX is JavaScript, a few HTML habits have to change:

HTML JSX Why
class="card" className="card" class is a reserved word in JavaScript
for="name" htmlFor="name" same reason — for is a loop keyword
<br> <br /> every tag must be closed
onclick="..." onClick={handleClick} camelCase, and the value is a function

Curly braces {} drop out of JSX back into JavaScript. Anything inside them must be an expression — a value, not a statement. {item.name}, {count * 2}, and {items.length === 0 ? "none" : "some"} all work. {if (x) {...}} does not.

A component must return one root element. For siblings with no wrapper, use a fragment, written <>...</>, which groups children without adding a DOM node.

Two minutes, once your project is running

Put {2 + 2} inside a heading in App.tsx and save. The browser shows 4. Now try {new Date().toLocaleTimeString()}. It is real JavaScript, evaluated when the component runs.

The render tree

Components use other components, so they form a tree. Your app has one root component, usually App, which returns elements including <Header /> and <EquipmentList />.

App
├── Header
├── SummaryCard  (label="Total units")
├── SummaryCard  (label="Needs service")
└── EquipmentList
    ├── EquipmentRow  (id="PUMP-3")
    └── EquipmentRow  (id="MTR-1")

React starts at the root, calls each component function, and follows the elements it returns until it has the full tree. That pass is called a render. Then it commits the result to the real DOM. SummaryCard appears twice — the same function, called twice with different props, producing two independent pieces of UI.

Data flows down this tree, from parent to child, through props. A child cannot reach up and change its parent's data. That one-directional flow is why you can read a React app by starting at the top.

An org chart with written briefings

Each component is handed a briefing (props) and produces one document. It can delegate parts downward, passing on a slice of that briefing. Nobody edits their manager's briefing — so to find out why a document says something wrong, you walk up the chart.

Working with AI today: tutor mode

Today's mode is tutor. A tutor-style request asks for an explanation, then one small example, then hands the problem back to you to attempt. A request that says "build the dashboard" produces code you cannot debug on Day 59 when it breaks.

Use this once your three components exist

"Explain this component tree as input/output blocks. Ask me which data belongs in each component."

Answer the questions yourself, out loud, before reading any follow-up explanation. If you cannot say which data belongs in SummaryCard, that is today's gap, and no generated code will close it.

Walkthrough

Create the project. Vite's React TypeScript template is the standard starting point.

cd ~/fullstack-journey
npm create vite@latest equipment-frontend -- --template react-ts
cd equipment-frontend
npm install
npm run dev

The dev server prints something like this (your version number will differ):

  VITE v7.0.4  ready in 412 ms

  ➜  Local:   http://localhost:5173/
  ➜  Network: use --host to expose
  ➜  press h + enter to show help

Open http://localhost:5173/. You get Vite's starter page. Now open src/main.tsx:

createRoot(document.getElementById('root')!).render(
  <StrictMode>
    <App />
  </StrictMode>,
)

That is the only handwritten DOM access in the whole app. index.html contains one empty <div id="root"></div>; createRoot claims it, and render(<App />) tells React to build the tree from App downward and put the result inside. Everything else is components.

Now replace the contents of src/App.tsx with your own root component:

function App() {
  return (
    <main>
      <h1>Equipment Dashboard</h1>
      <p>{3} units tracked</p>
    </main>
  );
}

export default App;

Save. The browser updates without a manual reload — Vite's hot module replacement, from Day 30.

Checkpoint

You should be able to say: what a component is, what JSX compiles into, and where in index.html React puts its output. If any of the three is fuzzy, reread that section now.

Your turn

Build the deliverable: a static component tree with clear props.

  1. In equipment-frontend, create src/types.ts with an exported type:

    export type Equipment = {
      id: string;
      name: string;
      location: string;
      status: "ok" | "needs-service" | "down";
    };
    

    The status union is Day 32 narrowing applied to UI data.

  2. Create src/data.ts exporting const equipment: Equipment[] with four hard-coded items. No network yet — Day 61 handles that.

  3. Create src/components/Header.tsx. It takes one prop, title: string, and returns a <header> containing an <h1>. Use semantic elements, as on Day 8 — not <div>.

  4. Create src/components/SummaryCard.tsx taking label: string and value: number.

  5. Create src/components/EquipmentList.tsx taking items: Equipment[]. Render a <ul> with one <li> per item using items.map(...) from Day 22. Give each <li> a key={item.id} attribute — React uses it to tell list entries apart between renders, and warns in the console without it.

  6. In App.tsx, import all three and compose them. Render <SummaryCard /> twice with different props, to prove one component serves both.

  7. Confirm it works: the page shows your header, two different cards, and four list items, and the browser console has no warnings.

You are done when

You can point at any element on screen and name which component function produced it, and which prop supplied each piece of text.

Common pitfalls

  • Lowercase component names. <summaryCard /> renders an unknown HTML tag and silently shows nothing useful. Capitalise every component.
  • Returning two elements. return <h1>..</h1><p>..</p>; is a syntax error. Wrap them in one element or a fragment <>...</>.
  • Using class instead of className. The style does not apply and React logs a warning. Same for for on a label, which must be htmlFor.
  • Putting statements in braces. {if (...) ...} fails. Use a ternary {cond ? a : b} or compute the value above the return.

Verify it yourself

Open today's reference, React's Build a React app from scratch, and find where it describes what a framework or build tool gives you beyond React itself.

  1. The page lists concerns React alone does not solve — routing is one. Find two, and note which week of this course handles each.
  2. This lesson said JSX compiles to a function call returning a plain object. Search react.dev for createElement and confirm what it returns: an element, or a DOM node?

Write both answers in notes/day-57.md. Confirming the compile step yourself is what keeps JSX from feeling like magic later.

The hour

  1. 0–5 min Recall

    Without notes, state yesterday’s main idea and one unresolved question.

  2. 5–20 min Learn

    Read only the listed concept notes and official reference sections needed today.

  3. 20–48 min Build

    Create a Vite React TypeScript project and split a static dashboard into Header, SummaryCard, and EquipmentList components.

  4. 48–55 min Explain and verify

    Run the result, inspect evidence, and explain the data/control flow in your own words.

  5. 55–60 min Quiz and commit

    Complete the quiz, record one lesson, and commit the verified change when applicable.

What to hand in

Deliverable

A static component tree with clear props.

Working with AI today

AI as tutor

Ask for explanations, analogies, questions, and hints. Do not request a complete finished solution first.

Explain this component tree as input/output blocks. Ask me which data belongs in each component.

References

End-of-day quiz

Q1 What is a React component?
Q2 Which result best proves today’s work is complete?
Q3 What is the best tutor-style AI request?

Explain-back gate

Pass the quiz above to unlock completion.

Quiz + explain-back checks required.