▶️ Live demo
Try it yourself — interact with the example below.
Loading demo…
🎯 What Is "Rendering a List from an Array"?
Imagine you're making a grocery list from a recipe:
MANUAL LIST (Hard-Coded JSX):
┌─────────────────────────────────────────┐
│ 📝 HANDWRITTEN GROCERY LIST │
│ │
│ • Milk │
│ • Eggs │
│ • Bread │
│ │
│ Problem: What if recipe has 20 items? │
│ You write each one by hand! │
│ What if ingredients change? │
│ You erase and rewrite everything! │
│ │
│ In React: │
│ <ul> │
│ <li>Milk</li> │
│ <li>Eggs</li> │
│ <li>Bread</li> │
│ </ul> │
│ // Boring! Repetitive! Error-prone! │
└─────────────────────────────────────────┘
DYNAMIC LIST (Array + map()):
┌─────────────────────────────────────────┐
│ 📱 SMART SHOPPING APP │
│ │
│ Recipe gives you an array: │
│ ["Milk", "Eggs", "Bread", "Butter"] │
│ │
│ App automatically creates list: │
│ • Milk │
│ • Eggs │
│ • Bread │
│ • Butter │
│ │
│ Add more ingredients? │
│ Just add to array! List updates! │
│ Delete one? Just remove from array! │
│ │
│ In React: │
│ const items = ["Milk", "Eggs", "Bread"];│
│ <ul> │
│ {items.map(item => <li>{item}</li>)} │
│ </ul> │
│ // Automatic! Scalable! Flexible! │
└─────────────────────────────────────────┘
THE "FAR AWAY" PACKING LIST:
┌─────────────────────────────────────────┐
│ 🎒 PACKING LIST ARRAY │
│ │
│ Each item is an OBJECT with details: │
│ │
│ { │
│ id: 1, ← Unique identifier │
│ description: "Passport", │
│ quantity: 1, ← How many │
│ packed: false ← Is it packed? │
│ } │
│ │
│ We map over this array to create: │
│ • 1 Passport ❌ (not packed) │
│ • 6 Socks ❌ (not packed) │
│ • 1 Charger ✓ (packed!) │
│ │
│ Packed items get STRIKE-THROUGH! │
└─────────────────────────────────────────┘
⚠️ The Big Problem: "How Do I Show Array Data?"
// ==========================================
// THE "MANUAL LIST" TRAP
// ==========================================
// ❌ WRONG: Writing each item by hand
function PackingList() {
return (
<div className="list">
<ul>
<li>Passport</li>
<li>Socks</li>
<li>Charger</li>
</ul>
</div>
);
}
// Problems:
// 1. What if you have 50 items? Write 50 <li>s?
// 2. What if data changes? Edit manually?
// 3. What if you need to sort? Rearrange manually?
// 4. No way to show quantity, packed status, etc.
// 5. Can't conditionally style (strikethrough for packed)
// ==========================================
// THE SOLUTION: Array + map() + Props
// ==========================================
// ✅ CORRECT: Store data in array, map to JSX
// Step 1: Create the data array
const initialItems = [
{ id: 1, description: "Passport", quantity: 1, packed: false },
{ id: 2, description: "Socks", quantity: 6, packed: false },
{ id: 3, description: "Charger", quantity: 1, packed: true },
];
// Step 2: Create component that receives ONE item
function Item({ item }) {
// item = { id: 1, description: "Passport", quantity: 1, packed: false }
return (
<li style={item.packed ? { textDecoration: "line-through" } : {}}>
<span>{item.quantity}</span>
<span>{item.description}</span>
<button>❌</button>
</li>
);
}
// Step 3: Map over array to create list
function PackingList() {
return (
<div className="list">
<ul>
{initialItems.map(item => (
<Item key={item.id} item={item} />
))}
</ul>
</div>
);
}
// What happens:
// initialItems[0] = { id: 1, description: "Passport", ... }
// → <Item key={1} item={firstObject} />
// → <li>1 Passport ❌</li>
//
// initialItems[1] = { id: 2, description: "Socks", ... }
// → <Item key={2} item={secondObject} />
// → <li>6 Socks ❌</li>
//
// initialItems[2] = { id: 3, description: "Charger", ... }
// → <Item key={3} item={thirdObject} />
// → <li>1 Charger ✓</li> (with strikethrough!)
📋 Complete Visual Examples
Create file: react-rendering-static-lists.js
// ==========================================
// RENDERING STATIC LISTS - Complete Guide
// ==========================================
/*
ARRAY TO JSX FLOW:
┌─────────────────────────────────────────┐
│ Array of Objects → map() → Components │
│ │
│ [{id:1, name:"A"}, {id:2, name:"B"}] │
│ ↓ │
│ .map(obj => <Component key={id} ... />)│
│ ↓ │
│ [<Component />, <Component />] │
│ ↓ │
│ Rendered in JSX! │
└─────────────────────────────────────────┘
CONDITIONAL STYLING:
┌─────────────────────────────────────────┐
│ Condition ? {style} : {} │
│ │
│ item.packed ? │
│ { textDecoration: "line-through" } │
│ : {} │
│ │
│ If packed → strike-through │
│ If not packed → no style (empty object)│
└─────────────────────────────────────────┘
*/
// ==========================================
// EXAMPLE 1: The Data Array
// ==========================================
// This is your "database" for now
// Each object represents ONE packing item
const initialItems = [
{ id: 1, description: "Passport", quantity: 1, packed: false },
{ id: 2, description: "Socks", quantity: 6, packed: false },
{ id: 3, description: "Charger", quantity: 1, packed: true },
{ id: 4, description: "Toothbrush", quantity: 2, packed: false },
];
// What each property means:
// id: Unique number (like a name tag)
// description: What the item is (text to show)
// quantity: How many (number to show)
// packed: true/false (is it in the suitcase?)
// ==========================================
// EXAMPLE 2: The Item Component (Receives Object)
// ==========================================
function Item({ item }) {
// Destructuring the prop:
// item = { id: 1, description: "Passport", quantity: 1, packed: false }
// We can also destructure further:
// function Item({ item: { description, quantity, packed } }) {
// // Now we can use description directly!
// }
return (
<li>
{/* Show quantity */}
<span style={{ marginRight: '10px', fontWeight: 'bold' }}>
{item.quantity}
</span>
{/* Show description */}
<span style={item.packed ? { textDecoration: "line-through" } : {}}>
{item.description}
</span>
{/* Delete button (just emoji for now) */}
<button style={{ marginLeft: '10px' }}>❌</button>
</li>
);
}
// Visual Breakdown for item = { id: 3, description: "Charger", quantity: 1, packed: true }:
//
// <li>
// <span>1</span> ← quantity: 1
// <span style={{textDecoration: "line-through"}}> ← packed: true!
// Charger ← description: "Charger"
// </span>
// <button>❌</button>
// </li>
//
// Result on screen: 1 ~~Charger~~ ❌
// (with strikethrough!)
// ==========================================
// EXAMPLE 3: The PackingList Component (Maps Array)
// ==========================================
function PackingList() {
return (
<div className="list">
<ul>
{/*
initialItems.map() goes through each object:
Iteration 1: item = {id: 1, description: "Passport", ...}
→ <Item key={1} item={firstObject} />
Iteration 2: item = {id: 2, description: "Socks", ...}
→ <Item key={2} item={secondObject} />
Iteration 3: item = {id: 3, description: "Charger", ...}
→ <Item key={3} item={thirdObject} />
*/}
{initialItems.map(item => (
<Item key={item.id} item={item} />
))}
</ul>
</div>
);
}
// The key prop is CRITICAL!
// React uses it to identify which item is which
// Always use a UNIQUE value (like id)
// NEVER use array index as key!
// ==========================================
// EXAMPLE 4: Conditional Style with Ternary
// ==========================================
function ItemWithStyle({ item }) {
return (
<li>
<span>{item.quantity}</span>
{/*
CONDITIONAL STYLE:
item.packed is true?
YES → apply {textDecoration: "line-through"}
NO → apply {} (empty, no styles)
*/}
<span style={item.packed ? { textDecoration: "line-through" } : {}}>
{item.description}
</span>
<button>❌</button>
</li>
);
}
// How the ternary works:
//
// item.packed = false
// false ? {textDecoration: "line-through"} : {}
// → {} (empty object, no styles applied)
// → Text looks normal
//
// item.packed = true
// true ? {textDecoration: "line-through"} : {}
// → {textDecoration: "line-through"}
// → Text has line through it!
// ==========================================
// EXAMPLE 5: Alternative - Conditional Class
// ==========================================
function ItemWithClass({ item }) {
return (
<li>
<span>{item.quantity}</span>
{/*
Alternative: Use CSS class instead of inline style
Requires CSS: .packed { text-decoration: line-through; }
*/}
<span className={item.packed ? "packed" : ""}>
{item.description}
</span>
<button>❌</button>
</li>
);
}
// CSS file:
// .packed {
// text-decoration: line-through;
// color: #999; /* Optional: gray out packed items */
// }
// ==========================================
// EXAMPLE 6: Complete App with All Components
// ==========================================
const initialItems = [
{ id: 1, description: "Passport", quantity: 1, packed: false },
{ id: 2, description: "Socks", quantity: 6, packed: false },
{ id: 3, description: "Charger", quantity: 1, packed: true },
{ id: 4, description: "Toothbrush", quantity: 2, packed: false },
];
function Logo() {
return <h1>🏝️ Far Away 💼</h1>;
}
function Form() {
return (
<div className="add-form">
<h3>What do you need for your 😍 trip?</h3>
</div>
);
}
function Item({ item }) {
return (
<li style={item.packed ? { textDecoration: "line-through" } : {}}>
<span style={{ marginRight: '10px' }}>{item.quantity}</span>
<span>{item.description}</span>
<button style={{ marginLeft: '10px', cursor: 'pointer' }}>❌</button>
</li>
);
}
function PackingList() {
return (
<div className="list">
<ul style={{ listStyle: 'none', padding: 0 }}>
{initialItems.map(item => (
<Item key={item.id} item={item} />
))}
</ul>
</div>
);
}
function Stats() {
return (
<footer className="stats">
<em>You have X items on your list and you already packed X (X%)</em>
</footer>
);
}
function App() {
return (
<div className="app">
<Logo />
<Form />
<PackingList />
<Stats />
</div>
);
}
🚀 Interactive React Usage Examples
Complete React File: StaticListRenderingMasterClass.jsx
import React, { useState } from 'react';
// ==========================================
// INTERACTIVE STATIC LIST RENDERING DEMO
// ==========================================
const initialItems = [
{ id: 1, description: "Passport", quantity: 1, packed: false },
{ id: 2, description: "Socks", quantity: 6, packed: false },
{ id: 3, description: "Charger", quantity: 1, packed: true },
{ id: 4, description: "Toothbrush", quantity: 2, packed: false },
{ id: 5, description: "Shampoo", quantity: 1, packed: true },
];
function StaticListRenderingMasterClass() {
const [activeDemo, setActiveDemo] = useState('array');
const demos = {
array: { title: 'The Array', component: <ArrayDemo /> },
map: { title: 'map() Method', component: <MapDemo /> },
item: { title: 'Item Component', component: <ItemComponentDemo /> },
conditional: { title: 'Conditional Style', component: <ConditionalStyleDemo /> },
complete: { title: 'Complete List', component: <CompleteListDemo /> }
};
return (
<div style={{ maxWidth: '900px', margin: '0 auto', padding: '20px', fontFamily: 'Arial, sans-serif' }}>
<header style={{ background: '#e76f51', color: 'white', padding: '30px', borderRadius: '10px', marginBottom: '30px' }}>
<h1 style={{ margin: 0 }}>📋 Rendering Static Lists</h1>
<p style={{ margin: '10px 0 0 0', opacity: 0.9 }}>From Array to JSX with Conditional Styling</p>
</header>
<nav style={{ display: 'flex', gap: '10px', marginBottom: '30px', flexWrap: 'wrap' }}>
{Object.entries(demos).map(([key, { title }]) => (
<button
key={key}
onClick={() => setActiveDemo(key)}
style={{
padding: '12px 24px',
fontSize: '16px',
border: 'none',
borderRadius: '8px',
cursor: 'pointer',
backgroundColor: activeDemo === key ? '#264653' : '#e0e0e0',
color: activeDemo === key ? 'white' : '#333',
fontWeight: activeDemo === key ? 'bold' : 'normal'
}}
>
{title}
</button>
))}
</nav>
<main style={{ background: '#f8f9fa', padding: '30px', borderRadius: '10px', minHeight: '400px' }}>
{demos[activeDemo].component}
</main>
</div>
);
}
// ==========================================
// DEMO 1: The Array
// ==========================================
function ArrayDemo() {
const [showExplanation, setShowExplanation] = useState(false);
return (
<div>
<h2>The Data Array 📦</h2>
<div style={{ marginBottom: '20px', padding: '15px', background: '#e3f2fd', borderRadius: '8px' }}>
<h4>Before we render, we need DATA!</h4>
</div>
<div style={{
padding: '20px',
background: '#1e1e1e',
color: '#d4d4d4',
borderRadius: '10px',
fontFamily: 'monospace',
fontSize: '14px',
overflow: 'auto'
}}>
<div style={{ color: '#6a9955' }}>// Array of objects - each is one item</div>
<div><span style={{ color: '#c586c0' }}>const</span> <span style={{ color: '#9cdcfe' }}>initialItems</span> = [</div>
{initialItems.map(item => (
<div key={item.id} style={{ marginLeft: '20px' }}>
{'{ '}
<span style={{ color: '#9cdcfe' }}>id</span>: <span style={{ color: '#b5cea8' }}>{item.id}</span>,{' '}
<span style={{ color: '#9cdcfe' }}>description</span>: <span style={{ color: '#ce9178' }}>"{item.description}"</span>,{' '}
<span style={{ color: '#9cdcfe' }}>quantity</span>: <span style={{ color: '#b5cea8' }}>{item.quantity}</span>,{' '}
<span style={{ color: '#9cdcfe' }}>packed</span>: <span style={{ color: '#569cd6' }}>{item.packed.toString()}</span>
{' }'}
{item.packed && <span style={{ color: '#6a9955', marginLeft: '10px' }}>← packed!</span>}
</div>
))}
<div>];</div>
</div>
<button
onClick={() => setShowExplanation(!showExplanation)}
style={{ marginTop: '20px', padding: '10px 20px', background: '#7950f2', color: 'white', border: 'none', borderRadius: '5px' }}
>
{showExplanation ? 'Hide' : 'Show'} Property Explanations
</button>
{showExplanation && (
<div style={{ marginTop: '20px', padding: '20px', background: '#fff3e0', borderRadius: '8px' }}>
<table style={{ width: '100%', borderCollapse: 'collapse' }}>
<thead>
<tr style={{ background: '#264653', color: 'white' }}>
<th style={{ padding: '10px', textAlign: 'left' }}>Property</th>
<th style={{ padding: '10px', textAlign: 'left' }}>Type</th>
<th style={{ padding: '10px', textAlign: 'left' }}>Purpose</th>
<th style={{ padding: '10px', textAlign: 'left' }}>Example</th>
</tr>
</thead>
<tbody>
<tr style={{ borderBottom: '1px solid #e0e0e0' }}>
<td style={{ padding: '10px', fontFamily: 'monospace', color: '#7950f2' }}>id</td>
<td style={{ padding: '10px' }}>Number</td>
<td style={{ padding: '10px' }}>Unique identifier (for key prop)</td>
<td style={{ padding: '10px' }}>1, 2, 3...</td>
</tr>
<tr style={{ borderBottom: '1px solid #e0e0e0' }}>
<td style={{ padding: '10px', fontFamily: 'monospace', color: '#7950f2' }}>description</td>
<td style={{ padding: '10px' }}>String</td>
<td style={{ padding: '10px' }}>What the item is</td>
<td style={{ padding: '10px' }}>"Passport"</td>
</tr>
<tr style={{ borderBottom: '1px solid #e0e0e0' }}>
<td style={{ padding: '10px', fontFamily: 'monospace', color: '#7950f2' }}>quantity</td>
<td style={{ padding: '10px' }}>Number</td>
<td style={{ padding: '10px' }}>How many to pack</td>
<td style={{ padding: '10px' }}>6 (for socks)</td>
</tr>
<tr>
<td style={{ padding: '10px', fontFamily: 'monospace', color: '#7950f2' }}>packed</td>
<td style={{ padding: '10px' }}>Boolean</td>
<td style={{ padding: '10px' }}>Is it in the suitcase?</td>
<td style={{ padding: '10px' }}>true/false</td>
</tr>
</tbody>
</table>
</div>
)}
</div>
);
}
// ==========================================
// DEMO 2: map() Method
// ==========================================
function MapDemo() {
const [showStep, setShowStep] = useState(0);
const steps = [
{ title: 'Start with Array', code: 'const items = [obj1, obj2, obj3];' },
{ title: 'Call .map()', code: 'items.map(item => ...)' },
{ title: 'Return JSX', code: '<Item key={item.id} item={item} />' },
{ title: 'Result', code: '[<Item />, <Item />, <Item />]' }
];
return (
<div>
<h2>The map() Method 🔄</h2>
<div style={{ marginBottom: '20px', padding: '15px', background: '#e3f2fd', borderRadius: '8px' }}>
<h4>Array.map() transforms each element into JSX!</h4>
</div>
<div style={{ display: 'flex', gap: '10px', marginBottom: '20px' }}>
{steps.map((s, i) => (
<button
key={i}
onClick={() => setShowStep(i)}
style={{
padding: '10px 20px',
border: 'none',
borderRadius: '5px',
cursor: 'pointer',
background: showStep === i ? '#264653' : '#e0e0e0',
color: showStep === i ? 'white' : '#333'
}}
>
Step {i + 1}
</button>
))}
</div>
<div style={{ padding: '30px', background: 'white', borderRadius: '10px', border: '2px solid #264653' }}>
<h3 style={{ color: '#264653', marginTop: 0 }}>{steps[showStep].title}</h3>
<pre style={{
background: '#1e1e1e',
color: '#d4d4d4',
padding: '20px',
borderRadius: '8px',
fontSize: '16px'
}}>
{steps[showStep].code}
</pre>
</div>
<div style={{ marginTop: '20px', padding: '15px', background: '#e8f5e9', borderRadius: '8px' }}>
<h4>🧠 How map() Works:</h4>
<ol>
<li>Start with array: <code>[obj1, obj2, obj3]</code></li>
<li>map() calls your function for EACH element</li>
<li>Your function returns JSX for that element</li>
<li>map() collects all JSX into a NEW array</li>
<li>React renders that array of JSX!</li>
</ol>
</div>
</div>
);
}
// ==========================================
// DEMO 3: Item Component
// ==========================================
function ItemComponentDemo() {
const [showProps, setShowProps] = useState(false);
const sampleItem = initialItems[2]; // Charger, packed: true
return (
<div>
<h2>The Item Component 🧩</h2>
<div style={{ marginBottom: '20px', padding: '15px', background: '#e3f2fd', borderRadius: '8px' }}>
<h4>Each array element becomes a component with props!</h4>
</div>
<div style={{ display: 'grid', gap: '20px', gridTemplateColumns: '1fr 1fr' }}>
<div style={{ padding: '20px', background: 'white', borderRadius: '8px', border: '2px solid #264653' }}>
<h3 style={{ color: '#264653', marginTop: 0 }}>Parent (PackingList):</h3>
<pre style={{
background: '#1e1e1e',
color: '#d4d4d4',
padding: '15px',
borderRadius: '4px',
fontSize: '13px'
}}>
{`{initialItems.map(item => (
<Item
key={item.id}
item={item}
/>
))}`}
</pre>
<p style={{ color: '#666', fontSize: '14px' }}>
Passes the entire object as <code>item</code> prop
</p>
</div>
<div style={{ padding: '20px', background: 'white', borderRadius: '8px', border: '2px solid #2a9d8f' }}>
<h3 style={{ color: '#2a9d8f', marginTop: 0 }}>Child (Item):</h3>
<pre style={{
background: '#1e1e1e',
color: '#d4d4d4',
padding: '15px',
borderRadius: '4px',
fontSize: '13px'
}}>
{`function Item({ item }) {
return (
<li>
<span>{item.quantity}</span>
<span>{item.description}</span>
<button>❌</button>
</li>
);
}`}
</pre>
<p style={{ color: '#666', fontSize: '14px' }}>
Receives object, accesses properties
</p>
</div>
</div>
<div style={{ marginTop: '20px', textAlign: 'center' }}>
<button
onClick={() => setShowProps(!showProps)}
style={{ padding: '10px 20px', background: '#7950f2', color: 'white', border: 'none', borderRadius: '5px' }}
>
{showProps ? 'Hide' : 'Show'} Props Flow Visualization
</button>
</div>
{showProps && (
<div style={{ marginTop: '20px', padding: '20px', background: '#fff3e0', borderRadius: '8px' }}>
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', gap: '20px', flexWrap: 'wrap' }}>
<div style={{ padding: '15px', background: '#e3f2fd', borderRadius: '8px', textAlign: 'center' }}>
<div style={{ fontWeight: 'bold', color: '#264653' }}>Array Object</div>
<pre style={{ fontSize: '12px', margin: '10px 0 0 0' }}>
{JSON.stringify(sampleItem, null, 2)}
</pre>
</div>
<div style={{ fontSize: '30px' }}>→</div>
<div style={{ padding: '15px', background: '#e8f5e9', borderRadius: '8px', textAlign: 'center' }}>
<div style={{ fontWeight: 'bold', color: '#2e7d32' }}>Prop: item</div>
<div style={{ fontSize: '14px', marginTop: '10px' }}>item.id = {sampleItem.id}</div>
<div style={{ fontSize: '14px' }}>item.description = "{sampleItem.description}"</div>
<div style={{ fontSize: '14px' }}>item.quantity = {sampleItem.quantity}</div>
<div style={{ fontSize: '14px' }}>item.packed = {sampleItem.packed.toString()}</div>
</div>
<div style={{ fontSize: '30px' }}>→</div>
<div style={{ padding: '15px', background: '#f3e5f5', borderRadius: '8px', textAlign: 'center' }}>
<div style={{ fontWeight: 'bold', color: '#7b1fa2' }}>Rendered JSX</div>
<div style={{ marginTop: '10px', padding: '10px', background: 'white', borderRadius: '4px' }}>
<span style={{ marginRight: '10px', fontWeight: 'bold' }}>{sampleItem.quantity}</span>
<span style={sampleItem.packed ? { textDecoration: 'line-through' } : {}}>{sampleItem.description}</span>
</div>
</div>
</div>
</div>
)}
</div>
);
}
// ==========================================
// DEMO 4: Conditional Style
// ==========================================
function ConditionalStyleDemo() {
const [packed, setPacked] = useState(false);
return (
<div>
<h2>Conditional Styling 🎨</h2>
<div style={{ marginBottom: '20px', padding: '15px', background: '#e3f2fd', borderRadius: '8px' }}>
<h4>Packed items get strike-through!</h4>
</div>
<div style={{
padding: '40px',
background: 'white',
borderRadius: '10px',
textAlign: 'center',
boxShadow: '0 2px 10px rgba(0,0,0,0.1)',
marginBottom: '20px'
}}>
<div style={{ marginBottom: '20px' }}>
<button
onClick={() => setPacked(!packed)}
style={{
padding: '15px 30px',
fontSize: '18px',
background: packed ? '#4caf50' : '#e0e0e0',
color: packed ? 'white' : '#333',
border: 'none',
borderRadius: '8px',
cursor: 'pointer'
}}
>
{packed ? '✓ Packed' : '❌ Not Packed'}
</button>
</div>
<div style={{ fontSize: '24px', padding: '20px', background: '#f5f5f5', borderRadius: '8px' }}>
<span style={{ marginRight: '10px', fontWeight: 'bold' }}>1</span>
<span style={packed ? { textDecoration: 'line-through', color: '#999' } : {}}>
Charger
</span>
</div>
</div>
<div style={{ display: 'grid', gap: '20px', gridTemplateColumns: '1fr 1fr' }}>
<div style={{ padding: '20px', background: '#ffebee', borderRadius: '8px' }}>
<h3 style={{ color: '#c62828', marginTop: 0 }}>The Ternary:</h3>
<pre style={{
background: '#1e1e1e',
color: '#d4d4d4',
padding: '15px',
borderRadius: '4px',
fontSize: '14px'
}}>
{`<span style={
item.packed
? { textDecoration: "line-through" }
: {}
}>
{item.description}
</span>`}
</pre>
</div>
<div style={{ padding: '20px', background: '#e8f5e9', borderRadius: '8px' }}>
<h3 style={{ color: '#2e7d32', marginTop: 0 }}>How It Works:</h3>
<div style={{ fontSize: '16px', lineHeight: '2' }}>
<p><strong>item.packed = false:</strong></p>
<p>false ? <span style={{ color: '#c62828' }}>strike-through</span> : <span style={{ color: '#2e7d32' }}>empty object</span></p>
<p>→ No style applied ✓</p>
<hr style={{ border: 'none', borderTop: '1px solid #e0e0e0', margin: '15px 0' }} />
<p><strong>item.packed = true:</strong></p>
<p>true ? <span style={{ color: '#c62828' }}>strike-through</span> : empty object</p>
<p>→ Text gets line through it ✓</p>
</div>
</div>
</div>
</div>
);
}
// ==========================================
// DEMO 5: Complete List
// ==========================================
function CompleteListDemo() {
return (
<div>
<h2>Complete Packing List ✅</h2>
<div style={{ marginBottom: '20px', padding: '15px', background: '#e3f2fd', borderRadius: '8px' }}>
<h4>Everything put together!</h4>
</div>
<div style={{
maxWidth: '400px',
margin: '0 auto',
background: 'white',
borderRadius: '10px',
overflow: 'hidden',
boxShadow: '0 4px 20px rgba(0,0,0,0.2)'
}}>
{/* Header */}
<div style={{ padding: '20px', background: '#e9c46a', color: '#264653', textAlign: 'center' }}>
<h2 style={{ margin: 0 }}>🏝️ Far Away 💼</h2>
</div>
{/* Form placeholder */}
<div style={{ padding: '15px', background: '#e76f51', color: 'white', textAlign: 'center' }}>
<em>What do you need for your 😍 trip?</em>
</div>
{/* The List */}
<div style={{ padding: '20px', background: '#f4a261', minHeight: '200px' }}>
<ul style={{ listStyle: 'none', padding: 0, margin: 0 }}>
{initialItems.map(item => (
<li
key={item.id}
style={{
padding: '12px',
marginBottom: '8px',
background: 'white',
borderRadius: '8px',
display: 'flex',
alignItems: 'center',
gap: '10px'
}}
>
<span style={{
background: '#7950f2',
color: 'white',
padding: '4px 10px',
borderRadius: '50%',
fontSize: '14px',
fontWeight: 'bold'
}}>
{item.quantity}
</span>
<span style={{
flex: 1,
textDecoration: item.packed ? 'line-through' : 'none',
color: item.packed ? '#999' : '#333'
}}>
{item.description}
</span>
<button style={{
background: 'none',
border: 'none',
cursor: 'pointer',
fontSize: '18px',
padding: '5px'
}}>
❌
</button>
</li>
))}
</ul>
</div>
{/* Stats */}
<div style={{ padding: '15px', background: '#2a9d8f', color: 'white', textAlign: 'center', fontSize: '14px' }}>
<em>You have {initialItems.length} items on your list and you already packed {initialItems.filter(i => i.packed).length} ({Math.round(initialItems.filter(i => i.packed).length / initialItems.length * 100)}%)</em>
</div>
</div>
<div style={{ marginTop: '20px', padding: '15px', background: '#e8f5e9', borderRadius: '8px' }}>
<h4>✅ What You Built:</h4>
<ul>
<li>Array of objects as data source</li>
<li>map() to transform array into JSX</li>
<li>Item component receiving object prop</li>
<li>key prop using unique id</li>
<li>Conditional style for packed items</li>
<li>Quantity badge, description, delete button</li>
</ul>
</div>
</div>
);
}
export default StaticListRenderingMasterClass;
🧠 Memory Aids for Poor Logic Thinking
The "Factory Assembly Line" Analogy
┌─────────────────────────────────────────────────┐
│ RENDERING A LIST = FACTORY ASSEMBLY LINE │
│ │
│ Raw Materials (Array): │
│ ┌─────────────────────────────────────────┐ │
│ │ [{id:1, name:"A"}, {id:2, name:"B"}] │ │
│ └─────────────────────────────────────────┘ │
│ ↓ │
│ Conveyor Belt (map()): │
│ ┌─────────────────────────────────────────┐ │
│ │ Item 1 → Worker 1 → Product 1 │ │
│ │ Item 2 → Worker 2 → Product 2 │ │
│ │ Item 3 → Worker 3 → Product 3 │ │
│ └─────────────────────────────────────────┘ │
│ ↓ │
│ Finished Products (JSX Array): │
│ [<Product />, <Product />, <Product />] │
│ ↓ │
│ Store Shelf (React DOM): │
│ • Product 1 │
│ • Product 2 │
│ • Product 3 │
│ │
│ In React: │
│ {items.map(item => <Item key={item.id} ... />)}│
│ │
│ Each "Worker" (map callback) receives ONE item │
│ and returns ONE JSX element! │
└─────────────────────────────────────────────────┘
The "Name Tag" Analogy for Props
┌─────────────────────────────────────────────────┐
│ PASSING OBJECT AS PROP = GIVING A FOLDER │
│ │
│ Parent has a folder with all info: │
│ ┌─────────────────────────────────────────┐ │
│ │ 📁 item folder │ │
│ │ • id: 3 │ │
│ │ • description: "Charger" │ │
│ │ • quantity: 1 │ │
│ │ • packed: true │ │
│ └─────────────────────────────────────────┘ │
│ │
│ Parent hands ENTIRE folder to child: │
│ <Item item={folder} /> │
│ ↑ │
│ "Here's the folder, handle it!" │
│ │
│ Child opens folder and uses what they need: │
│ function Item({ item }) { │
│ return ( │
│ <span>{item.quantity}</span> ← Opens folder│
│ <span>{item.description}</span> │
│ ); │
│ } │
│ │
│ Alternative: Destructure immediately │
│ function Item({ item: { description, packed } })│
│ // Now you can use 'description' directly! │
│ │
│ Like taking papers OUT of the folder first! │
└─────────────────────────────────────────────────┘
The "Highlighter Pen" Analogy for Conditional Style
┌─────────────────────────────────────────────────┐
│ CONDITIONAL STYLE = HIGHLIGHTER PEN │
│ │
│ You have a list of homework assignments: │
│ │
│ ┌─────────────────────────────────────────┐ │
│ │ Homework List: │ │
│ │ │ │
│ │ • Math problems [NOT DONE] │ │
│ │ → No highlighter (normal text) │ │
│ │ │ │
│ │ • Science essay [DONE ✓] │ │
│ │ → ~~Science essay~~ (crossed out) │ │
│ │ │ │
│ │ • History reading [NOT DONE] │ │
│ │ → No highlighter (normal text) │ │
│ │ │ │
│ │ • English poem [DONE ✓] │ │
│ │ → ~~English poem~~ (crossed out) │ │
│ └─────────────────────────────────────────┘ │
│ │
│ The rule: │
│ IF done → cross it out │
│ IF not done → leave it normal │
│ │
│ In React: │
│ <span style={item.packed ? {textDecoration: "line-through"} : {}}>│
│ {item.description} │
│ </span> │
│ │
│ Like a smart highlighter that only crosses out │
│ the DONE items automatically! │
└─────────────────────────────────────────────────┘
The "Key Prop" Analogy
┌─────────────────────────────────────────────────┐
│ KEY PROP = NAME TAGS AT A PARTY │
│ │
│ Imagine a party with 3 people: │
│ │
│ ❌ WITHOUT NAME TAGS (using array index): │
│ ┌─────────────────────────────────────────┐ │
│ │ Person 1: "I'm at position 0" │ │
│ │ Person 2: "I'm at position 1" │ │
│ │ Person 3: "I'm at position 2" │ │
│ │ │ │
│ │ Problem: If Person 2 leaves, │ │
│ │ Person 3 becomes "position 1"! │ │
│ │ React gets confused! "Who moved?" │ │
│ └─────────────────────────────────────────┘ │
│ │
│ ✅ WITH NAME TAGS (using unique id): │
│ ┌─────────────────────────────────────────┐ │
│ │ Person 1: "My name is Alice (id: 1)" │ │
│ │ Person 2: "My name is Bob (id: 2)" │ │
│ │ Person 3: "My name is Carol (id: 3)" │ │
│ │ │ │
│ │ If Bob leaves, Carol is STILL id: 3 │ │
│ │ React knows exactly who is who! │ │
│ └─────────────────────────────────────────┘ │
│ │
│ ALWAYS use a UNIQUE, STABLE identifier! │
│ NEVER use array index as key! │
│ │
│ Good keys: id, username, email, UUID │
│ Bad keys: array index, random number, Date.now() │
└─────────────────────────────────────────────────┘
🎓 Practice Exercises
Exercise 1: Render a Simple Array
Render this array as a list:
const fruits = ["Apple", "Banana", "Cherry", "Date"];
function FruitList() {
// TODO: Use map() to render each fruit as <li>
return (
<ul>
{/* Your code here */}
</ul>
);
}
Solution:
function FruitList() {
const fruits = ["Apple", "Banana", "Cherry", "Date"];
return (
<ul>
{fruits.map((fruit, index) => (
<li key={index}>{fruit}</li>
))}
</ul>
);
}
// Note: For simple arrays without objects, index is OK as key
// But for objects with id, ALWAYS use id!
Exercise 2: Render Array of Objects
Render this array with all properties:
const students = [
{ id: 1, name: "Alice", grade: "A" },
{ id: 2, name: "Bob", grade: "B" },
{ id: 3, name: "Carol", grade: "A+" }
];
function StudentList() {
// TODO: Create Student component
// TODO: Map over array, pass each student as prop
// TODO: Show name and grade
return (
<div>
{/* Your code here */}
</div>
);
}
Solution:
function Student({ student }) {
return (
<li style={{
padding: '10px',
marginBottom: '5px',
background: student.grade.startsWith('A') ? '#e8f5e9' : '#fff3e0',
borderRadius: '5px'
}}>
<strong>{student.name}</strong> — Grade: {student.grade}
</li>
);
}
function StudentList() {
const students = [
{ id: 1, name: "Alice", grade: "A" },
{ id: 2, name: "Bob", grade: "B" },
{ id: 3, name: "Carol", grade: "A+" }
];
return (
<div style={{ padding: '20px' }}>
<h2>Students</h2>
<ul style={{ listStyle: 'none', padding: 0 }}>
{students.map(student => (
<Student key={student.id} student={student} />
))}
</ul>
</div>
);
}
Exercise 3: Conditional Styling
Add strike-through for completed tasks:
const tasks = [
{ id: 1, text: "Learn React", completed: true },
{ id: 2, text: "Build an app", completed: false },
{ id: 3, text: "Get a job", completed: false }
];
function TaskList() {
// TODO: Add conditional style for completed tasks
return (
<ul>
{tasks.map(task => (
<li key={task.id}>
{task.text}
</li>
))}
</ul>
);
}
Solution:
function TaskList() {
const tasks = [
{ id: 1, text: "Learn React", completed: true },
{ id: 2, text: "Build an app", completed: false },
{ id: 3, text: "Get a job", completed: false }
];
return (
<ul style={{ listStyle: 'none', padding: 0 }}>
{tasks.map(task => (
<li
key={task.id}
style={{
padding: '15px',
marginBottom: '8px',
background: 'white',
borderRadius: '8px',
textDecoration: task.completed ? 'line-through' : 'none',
color: task.completed ? '#999' : '#333'
}}
>
<span style={{ marginRight: '10px' }}>
{task.completed ? '✅' : '⬜'}
</span>
{task.text}
</li>
))}
</ul>
);
}
Exercise 4: Complete the Packing Item
Finish the Item component with all features:
const initialItems = [
{ id: 1, description: "Passport", quantity: 1, packed: false },
{ id: 2, description: "Socks", quantity: 6, packed: true },
{ id: 3, description: "Charger", quantity: 1, packed: false }
];
function Item({ item }) {
// TODO: Show quantity
// TODO: Show description with strike-through if packed
// TODO: Show delete button (❌)
return (
<li>
{/* Your code here */}
</li>
);
}
function PackingList() {
// TODO: Map over initialItems
// TODO: Pass each item to Item component with key
return (
<div className="list">
<ul>
{/* Your code here */}
</ul>
</div>
);
}
Solution:
function Item({ item }) {
return (
<li style={{
padding: '12px',
marginBottom: '8px',
background: 'white',
borderRadius: '8px',
display: 'flex',
alignItems: 'center',
gap: '12px'
}}>
{/* Quantity badge */}
<span style={{
background: '#7950f2',
color: 'white',
padding: '4px 12px',
borderRadius: '50%',
fontWeight: 'bold',
fontSize: '14px'
}}>
{item.quantity}
</span>
{/* Description with conditional strike-through */}
<span style={{
flex: 1,
textDecoration: item.packed ? 'line-through' : 'none',
color: item.packed ? '#999' : '#333',
fontSize: '16px'
}}>
{item.description}
</span>
{/* Delete button */}
<button style={{
background: 'none',
border: 'none',
cursor: 'pointer',
fontSize: '20px',
padding: '5px'
}}>
❌
</button>
</li>
);
}
function PackingList() {
const initialItems = [
{ id: 1, description: "Passport", quantity: 1, packed: false },
{ id: 2, description: "Socks", quantity: 6, packed: true },
{ id: 3, description: "Charger", quantity: 1, packed: false }
];
return (
<div className="list" style={{ padding: '20px', background: '#f4a261' }}>
<ul style={{ listStyle: 'none', padding: 0, margin: 0 }}>
{initialItems.map(item => (
<Item key={item.id} item={item} />
))}
</ul>
</div>
);
}
💡 Key Takeaways
| Concept | What It Means | Example |
|---|---|---|
| Array of objects | Data stored as objects with properties | { id: 1, description: "Passport", packed: false } |
| map() | Transform array elements into JSX | items.map(item => <Item ... />) |
| Object as prop | Pass entire object to child component | <Item item={item} /> |
| Destructuring | Extract properties from object | function Item({ item }) { ... } |
| key prop | Unique identifier for React | key={item.id} |
| Conditional style | Apply styles based on condition | style={packed ? {textDecoration: "line-through"} : {}} |
| Ternary for style | Choose between style objects | condition ? {styleA} : {styleB} |
| Empty object | No styles applied | {} |
The Complete Pattern:
// 1. Data array
const items = [
{ id: 1, description: "Passport", quantity: 1, packed: false },
{ id: 2, description: "Socks", quantity: 6, packed: true }
];
// 2. Component that receives one item
function Item({ item }) {
return (
<li style={item.packed ? { textDecoration: "line-through" } : {}}>
<span>{item.quantity}</span>
<span>{item.description}</span>
<button>❌</button>
</li>
);
}
// 3. Parent that maps over array
function PackingList() {
return (
<ul>
{items.map(item => (
<Item key={item.id} item={item} />
))}
</ul>
);
}
Golden Rules:
- Store data in arrays of objects — Each object = one item with all its properties
- Use map() to render lists — Never write JSX manually for each item
- Always use key prop — Must be unique and stable (use id, never index)
- Pass entire object as prop —
<Item item={item} />is clean - Destructuring in child —
function Item({ item })for easy access - Conditional style with ternary —
condition ? {styles} : {} - Empty object = no styles —
{}is the "default" style - Semantic HTML —
<ul>and<li>for lists, not<div>s
One Sentence Summary: > "To render a static list in React, you store your data as an array of objects where each object has a unique id and properties like description and packed status, then use the map method to transform each object into a JSX component by passing the entire object as a prop with a key set to the unique id, and inside the child component you destructure the object to access its properties while using a ternary operator to conditionally apply an inline style object like {textDecoration: 'line-through'} when the packed property is true or an empty object {} when it's false!"