What Are We Building?
Imagine you're following a recipe with numbered steps:
THE FINAL GOAL (Interactive - Future):
┌─────────────────────────────────────────┐
│ RECIPE STEPS │
│ │
│ ┌────┐ ┌────┐ ┌────┐ │
│ │ 1 │ │ 2 │ │ 3 │ │
│ │ │ │ │ │ │ │
│ └────┘ └────┘ └────┘ │
│ │
│ Step 1: Gather ingredients │
│ │
│ [Previous] [Next] │
│ │
│ Click Next → Step 2 highlights │
│ Click Next → Step 3 highlights │
│ │
│ In React: Will need STATE (future!) │
└─────────────────────────────────────────┘
WHAT WE BUILD NOW (Static - Today's lesson):
┌─────────────────────────────────────────┐
│ STATIC RECIPE STEPS │
│ │
│ ┌────┐ ┌────┐ ┌────┐ │
│ │ 1 │ │ 2 │ │ 3 │ │
│ │ │ │ │ │ │ │
│ └────┘ └────┘ └────┘ │
│ │
│ Step 1: Gather ingredients │
│ │
│ [Previous] [Next] │
│ │
│ Buttons don't work yet! │
│ We manually set which step is active│
│ │
│ In React: Pure JSX, no state yet │
└─────────────────────────────────────────┘
KEY INSIGHT:
Static = "The picture frame"
Interactive = "The picture frame + working buttons"
You MUST build the frame before adding the mechanics!
The Big Problem: "How Do I Start a New Project?"
// ==========================================
// THE "WHERE DO I BEGIN?" CONFUSION
// ==========================================
// WRONG: Trying to add this to an existing pizza project
// WRONG: Mixing old code with new code
// WRONG: Not organizing projects properly
// ==========================================
// THE SOLUTION: Create a Brand New Project
// ==========================================
// Terminal commands (step by step):
// 1. Navigate to where you want the project
cd Desktop
// 2. Create new React app (version 5 for consistency)
npx create-react-app@5 steps
// 3. Wait for installation...
// 4. Open in VS Code:
// - Drag folder to VS Code
// OR
// - cd steps
// - code .
// Visual:
// Your Computer
// ┌─────────────────────────────────────────┐
// │ Desktop │
// │ ├── pizza-project (old) │
// │ ├── steps (NEW! ) │
// │ │ ├── node_modules │
// │ │ ├── public │
// │ │ ├── src │
// │ │ │ ├── App.js │
// │ │ │ ├── index.js │
// │ │ │ └── ... │
// │ │ └── package.json │
// │ └── ... │
// └─────────────────────────────────────────┘
Step-by-Step Project Setup
┌─────────────────────────────────────────────────┐
│ STEP 1: CLEAN UP STARTER FILES │
│ │
│ Delete these files from src/ folder: │
│ App.css │
│ App.test.js │
│ logo.svg │
│ reportWebVitals.js │
│ setupTests.js │
│ │
│ Keep these files: │
│ App.js │
│ index.js │
│ │
│ Why? We want a clean slate! │
└─────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────┐
│ STEP 2: CLEAN UP INDEX.JS │
│ │
│ BEFORE (messy): │
│ import React from 'react'; │
│ import ReactDOM from 'react-dom/client'; │
│ import './index.css'; │
│ import App from './App'; │
│ import reportWebVitals from './reportWebVitals';│
│ │
│ AFTER (clean): │
│ import React from 'react'; │
│ import ReactDOM from 'react-dom/client'; │
│ import './index.css'; │
│ import App from './App'; │
│ │
│ Remove: reportWebVitals import and usage │
└─────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────┐
│ STEP 3: ADD PROVIDED FILES │
│ │
│ From the course starter files: │
│ • Copy index.css → src/index.css │
│ • Copy vanilla.html → public/vanilla.html │
│ │
│ Why? The CSS has styles we need! │
│ The HTML is for reference. │
└─────────────────────────────────────────────────┘
Building the Static Component
Complete Code: src/App.js
// ==========================================
// STEP 4: CREATE THE APP COMPONENT
// ==========================================
// Data lives OUTSIDE the component
// (so it doesn't get recreated on every render)
const messages = [
"Learn React ",
"Apply for jobs ",
"Invest your new income "
];
// The App component - root of our application
function App() {
// Static variable (manually set for now)
// Later we'll make this dynamic with state!
const step = 1;
return (
<div className="steps">
{/* STEP NUMBERS */}
<div className="numbers">
<div className={`${step >= 1 ? "active" : ""}`}>1</div>
<div className={`${step >= 2 ? "active" : ""}`}>2</div>
<div className={`${step >= 3 ? "active" : ""}`}>3</div>
</div>
{/* STEP MESSAGE */}
<p className="message">
Step {step}: {messages[step - 1]}
{/* step - 1 because arrays start at 0! */}
{/* step 1 → messages[0] → "Learn React " */}
{/* step 2 → messages[1] → "Apply for jobs " */}
{/* step 3 → messages[2] → "Invest your new income " */}
</p>
{/* BUTTONS */}
<div className="buttons">
<button
style={{ backgroundColor: "#7950f2", color: "#fff" }}
>
Previous
</button>
<button
style={{ backgroundColor: "#7950f2", color: "#fff" }}
>
Next
</button>
</div>
</div>
);
}
export default App;
// Visual Structure:
// ┌─────────────────────────────────────────┐
// │ <div className="steps"> │
// │ ┌─────────────────────────────┐ │
// │ │ <div className="numbers"> │ │
// │ │ <div>1</div> ← active │ │
// │ │ <div>2</div> │ │
// │ │ <div>3</div> │ │
// │ └─────────────────────────────┘ │
// │ ┌─────────────────────────────┐ │
// │ │ <p className="message"> │ │
// │ │ Step 1: Learn React │ │
// │ └─────────────────────────────┘ │
// │ ┌─────────────────────────────┐ │
// │ │ <div className="buttons"> │ │
// │ │ <button>Previous</button> │ │
// │ │ <button>Next</button> │ │
// │ └─────────────────────────────┘ │
// └─────────────────────────────────────────┘
Key Concepts Explained
Concept 1: App as Root Component
┌─────────────────────────────────────────────────┐
│ WHY IS THE COMPONENT CALLED "App"? │
│ │
│ Think of a tree: │
│ │
│ App (Root) │
│ / \ │
│ Header Main │
│ / \ │
│ Sidebar Content │
│ / \ │
│ Article Comments │
│ │
│ App is the PARENT of everything! │
│ It's the entry point. │
│ index.js renders <App /> into the DOM. │
│ │
│ Convention: Always name your root component App │
│ (like naming your main file "index") │
└─────────────────────────────────────────────────┘
Concept 2: Data Outside Component
┌─────────────────────────────────────────────────┐
│ WHY PUT DATA OUTSIDE THE COMPONENT? │
│ │
│ WRONG: Data inside component │
│ ┌─────────────────────────────────────────┐ │
│ │ function App() { │ │
│ │ const messages = [...]; ← │ │
│ │ // Created EVERY TIME App runs! │ │
│ │ return (...); │ │
│ │ } │ │
│ └─────────────────────────────────────────┘ │
│ ↓ │
│ Every render = new array created = waste! │
│ │
│ CORRECT: Data outside component │
│ ┌─────────────────────────────────────────┐ │
│ │ const messages = [...]; ← │ │
│ │ // Created ONCE when file loads! │ │
│ │ │ │
│ │ function App() { │ │
│ │ return (...); │ │
│ │ } │ │
│ └─────────────────────────────────────────┘ │
│ ↓ │
│ Array created once, reused forever! │
│ │
│ RULE: If data never changes, put it outside! │
└─────────────────────────────────────────────────┘
Concept 3: Inline Styles in JSX
┌─────────────────────────────────────────────────┐
│ INLINE STYLES = JAVASCRIPT OBJECTS │
│ │
│ In HTML: │
│ <button style="background-color: purple;"> │
│ │
│ In JSX: │
│ <button style={{ backgroundColor: "#7950f2" }}>│
│ ↑ │
│ Double curly braces! │
│ │
│ WHY DOUBLE CURLY BRACES? │
│ ┌─────────────────────────────────────────┐ │
│ │ Outer { } = "Enter JavaScript mode" │ │
│ │ Inner { } = "This is a JS object" │ │
│ │ │ │
│ │ style={ ← JSX JavaScript │ │
│ │ { ← Object starts │ │
│ │ backgroundColor: "#7950f2", │ │
│ │ color: "#fff" │ │
│ │ } ← Object ends │ │
│ │ } ← JSX JavaScript ends │ │
│ └─────────────────────────────────────────┘ │
│ │
│ CSS → JS CONVERSIONS: │
│ ┌─────────────────┬─────────────────────────┐ │
│ │ CSS │ JSX (camelCase) │ │
│ ├─────────────────┼─────────────────────────┤ │
│ │ background-color│ backgroundColor │ │
│ │ font-size │ fontSize │ │
│ │ border-radius │ borderRadius │ │
│ │ margin-top │ marginTop │ │
│ │ text-align │ textAlign │ │
│ └─────────────────┴─────────────────────────┘ │
│ │
│ VALUES MUST BE STRINGS OR NUMBERS: │
│ color: "#fff" │
│ fontSize: 16 │
│ fontSize: "16px" │
│ color: #fff (missing quotes!) │
└─────────────────────────────────────────────────┘
Concept 4: Conditional Class Names
┌─────────────────────────────────────────────────┐
│ CONDITIONAL CLASS NAMES EXPLAINED │
│ │
│ GOAL: Highlight step 1, but not 2 and 3 │
│ (when step = 1) │
│ │
│ Template Literal: `string ${condition ? "A" : "B"}`│
│ │
│ For step 1: │
│ ┌─────────────────────────────────────────┐ │
│ │ step = 1 │ │
│ │ │ │
│ │ Step 1 div: │ │
│ │ className={`${step >= 1 ? "active" : ""}`}│ │
│ │ // 1 >= 1 → true → "active" │ │
│ │ // Result: "active" │ │
│ │ // CSS makes it purple! │ │
│ │ │ │
│ │ Step 2 div: │ │
│ │ className={`${step >= 2 ? "active" : ""}`}│ │
│ │ // 1 >= 2 → false → "" │ │
│ │ // Result: "" (empty string) │ │
│ │ // No special styling │ │
│ │ │ │
│ │ Step 3 div: │ │
│ │ className={`${step >= 3 ? "active" : ""}`}│ │
│ │ // 1 >= 3 → false → "" │ │
│ │ // Result: "" (empty string) │ │
│ └─────────────────────────────────────────┘ │
│ │
│ For step 2: │
│ ┌─────────────────────────────────────────┐ │
│ │ step = 2 │ │
│ │ │ │
│ │ Step 1: 2 >= 1 → true → "active" │ │
│ │ Step 2: 2 >= 2 → true → "active" │ │
│ │ Step 3: 2 >= 3 → false → "" │ │
│ │ │ │
│ │ Result: Steps 1 & 2 are highlighted! │ │
│ └─────────────────────────────────────────┘ │
│ │
│ WHY >= (greater than or equal)? │
│ Because when you're on step 2, │
│ steps 1 AND 2 should both look "completed" │
│ (depending on your CSS design) │
└─────────────────────────────────────────────────┘
Concept 5: Array Indexing (Zero-Based)
┌─────────────────────────────────────────────────┐
│ WHY DO WE USE step - 1? │
│ │
│ ARRAYS START AT 0, HUMANS START AT 1! │
│ │
│ Array: messages = ["A", "B", "C"] │
│ Index: 0 1 2 │
│ │
│ Step number (UI): 1 2 3 │
│ Array index: 0 1 2 │
│ │
│ ┌─────────────────────────────────────────┐ │
│ │ When step = 1: │ │
│ │ messages[step - 1] │ │
│ │ messages[1 - 1] │ │
│ │ messages[0] │ │
│ │ → "Learn React " │ │
│ └─────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────┐ │
│ │ When step = 2: │ │
│ │ messages[step - 1] │ │
│ │ messages[2 - 1] │ │
│ │ messages[1] │ │
│ │ → "Apply for jobs " │ │
│ └─────────────────────────────────────────┘ │
│ │
│ WITHOUT -1: │
│ messages[1] when step=1 → "Apply for jobs" │
│ Wrong message for step 1! │
│ │
│ WITH -1: │
│ messages[0] when step=1 → "Learn React" │
│ Correct! │
└─────────────────────────────────────────────────┘
Practice Exercises
Exercise 1: Add Step 4
Add a 4th step to the component:
const messages = [
"Learn React ",
"Apply for jobs ",
"Invest your new income ",
// TODO: Add 4th step
];
function App() {
const step = 1;
return (
<div className="steps">
<div className="numbers">
<div className={`${step >= 1 ? "active" : ""}`}>1</div>
<div className={`${step >= 2 ? "active" : ""}`}>2</div>
<div className={`${step >= 3 ? "active" : ""}`}>3</div>
{/* TODO: Add step 4 */}
</div>
{/* ... rest of component */}
</div>
);
}
Solution:
const messages = [
"Learn React ",
"Apply for jobs ",
"Invest your new income ",
"Retire early " // Added 4th step
];
function App() {
const step = 1;
return (
<div className="steps">
<div className="numbers">
<div className={`${step >= 1 ? "active" : ""}`}>1</div>
<div className={`${step >= 2 ? "active" : ""}`}>2</div>
<div className={`${step >= 3 ? "active" : ""}`}>3</div>
<div className={`${step >= 4 ? "active" : ""}`}>4</div>
</div>
<p className="message">
Step {step}: {messages[step - 1]}
</p>
{/* buttons */}
</div>
);
}
Exercise 2: Fix the Style Bug
This button style is broken. Fix it:
<button style={ backgroundColor: "#7950f2" }>
Click me
</button>
Bug: Missing curly braces around the object.
Solution:
<button style={{ backgroundColor: "#7950f2" }}>
Click me
</button>
Exercise 3: Create a Progress Bar
Create a simple progress bar component:
function ProgressBar({ current, total }) {
// TODO: Show current step out of total
// Example: current=2, total=5 → "Step 2 of 5"
return (
<div>
{/* Your code here */}
</div>
);
}
Solution:
function ProgressBar({ current, total }) {
return (
<div className="progress-bar">
<p>Step {current} of {total}</p>
<div className="bar">
<div
style={{
width: `${(current / total) * 100}%`,
backgroundColor: "#7950f2",
height: "10px"
}}
/>
</div>
</div>
);
}
Key Takeaways
| Concept | What It Means | Example |
|---|---|---|
| Create React App | Tool to start new projects | npx create-react-app@5 steps |
| App Component | Root component of application | function App() { return ... } |
| Static Data | Data that doesn't change | Put outside component |
| Inline Styles | CSS via JavaScript object | style={{ color: "red" }} |
| Conditional Classes | Dynamic class names | ` className={${step >= 1 ? "active" : ""}} ` |
| Array Index | Arrays start at 0 | messages[step - 1] |
| Template Literal | String with embedded JS | ` text ${variable} ` |
The Static Component Pattern:
// 1. Data outside
const data = [...];
// 2. Component function
function App() {
// 3. Static variables (for now)
const step = 1;
// 4. Return JSX
return (
<div>
{/* Conditional classes */}
<div className={`${step >= 1 ? "active" : ""}`}>1</div>
{/* Dynamic content from array */}
<p>{data[step - 1]}</p>
{/* Styled buttons */}
<button style={{ backgroundColor: "purple" }}>
Next
</button>
</div>
);
}
Golden Rules:
- One project per app - Don't mix projects
- Clean up starter files - Remove what you don't need
- Static data goes outside - Don't recreate on every render
- Double curly braces for styles -
{ { } } - CSS properties become camelCase -
background-color→backgroundColor - Arrays start at 0 - Always remember
step - 1for human numbering
One Sentence Summary: > "To build a static steps component, create a new React project, define your step data outside the component, use template literals with ternary operators to conditionally add 'active' CSS classes to step numbers, use step - 1 to convert human-friendly step numbers to zero-based array indices for retrieving messages, and apply inline styles with double curly braces objects to make buttons purple - all without any state or interactivity yet, just pure JSX laying the foundation for future functionality!"