FullStackOpen Part 1 A Introduction To React
FullStackOpen Part 1 A Introduction To React
md 2025-08-08
🧩 If the section is deep, technical, or essential for backend/frontend architecture: Use the Full Detailed
Format with the following goals: ✅ Core Objectives Clearly explain the concepts using beginner-friendly but
technically sound language Demonstrate how each idea applies to real-world MERN projects (e.g., REST APIs,
component state, Express middleware) Include code snippets, project structures, or diagrams where helpful
Summarize all necessary key takeaways — cover everything essential to fully understand the content Identify
and explain core concepts to retain for long-term understanding Highlight common pitfalls,
misunderstandings, or mistakes beginners might face Describe how this section fits into the broader MERN
learning path (e.g., frontend foundations, backend APIs, database logic)
🧩 Bonus Learning Tools (as appropriate): Interview-style Q&A Conceptual (e.g., “What does useEffect do?”)
Technical (e.g., “Fix this Express route” or “Write a Mongoose schema”)
🧠 Mini Quiz or Checkpoints Create a mini quiz or checkpoint with enough questions to ensure full
understanding of the section. For each question, provide the correct answer immediately after to help
reinforce learning and allow self-assessment. Use a mix of conceptual, technical, and applied questions where
appropriate.
⚡ If the section is introductory or covers a small utility or isolated topic: Use the Lightweight Format with the
following goals: ✅ What to Do Provide a clear and concise explanation Share relevant examples or code
snippets List important concepts worth remembering Summarize the section with as many key insights as
needed (no fixed limit) Mention any common beginner mistakes
🧩 Optional (as needed): Include interview-style Q&As to reinforce core ideas 🧠 Mini Quiz or Checkpoints If
helpful, create a checkpoint quiz with as many questions as necessary to ensure full understanding. For each
question, provide the correct answer immediately after it. Focus on concise, practical, and concept-reinforcing
questions.
➡ Please tailor your explanation to someone who is actively learning the MERN stack and building real-world
projects for interviews or portfolio development. Decide which format (detailed or lightweight) is appropriate
based on the content you receive next.
I understand! I'm ready to help you learn and retain information from the FullStackOpen course in a way that's
tailored to your MERN stack journey and software engineering preparation.
1 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
I'll analyze the content you provide next and choose the appropriate format:
Given your background as a MERN/Java developer focused on scalable systems and your preference for first-
principles explanations, I'll ensure the content is:
Please go ahead and share the FullStackOpen section or excerpt you'd like me to explain!
Why Vite? It's significantly faster than Create React App due to:
2 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
ReactDOM.createRoot(document.getElementById('root')).render(<App />)
3 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
main.jsx serves as the bridge between your React app and the HTML DOM
Clean project structure - remove unused files early to avoid confusion
Port 5173 is Vite's default (auto-increments if busy)
Q2: What does ReactDOM.createRoot() do? A2: It creates a root DOM node where React will render your
application, connecting React to the HTML element with id "root"
Q3: What's the difference between App.jsx and main.jsx? A3: main.jsx is the entry point that mounts the
app to the DOM, while App.jsx is your root React component that contains your application logic
Q4: Why must React component names start with a capital letter? A4: React uses capitalization to
distinguish between custom components and regular HTML elements. Lowercase names are treated as DOM
elements.
Q5: What port does Vite use by default? A5: Port 5173 (and automatically finds the next available port if
5173 is busy)
This foundation is crucial - every MERN project starts here, and understanding this setup will make complex
React concepts much easier to grasp!
React is a JavaScript library for building user interfaces, specifically the "R" in your MERN stack. It's
component-based, meaning you build encapsulated components that manage their own state and compose
them to create complex UIs.
Real-world significance: In production MERN applications, React handles the entire frontend layer - from
simple landing pages to complex dashboards with real-time data from your Express/Node.js APIs.
Vite vs Create React App: The course uses Vite (pronounced "veet") instead of the older Create React App.
Vite is significantly faster because it uses ES modules and hot module replacement (HMR), making your
development experience much smoother.
4 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
# vs older approach
npx create-react-app my-app # Slower, deprecated
ReactDOM.createRoot(document.getElementById('root')).render(<App />)
Real-world application: This pattern scales to any React app. Whether you're building a simple portfolio or a
complex e-commerce dashboard, this entry point remains consistent.
Key concepts:
// ❌ Wrong
const App = () => {
<div>Hello</div> // Missing return
}
// ✅ Correct
const App = () => {
return <div>Hello</div>
}
// ❌ Wrong
const App = () => {
return (
<h1>Title</h1>
<p>Content</p> // Can't return multiple elements
)
}
<div>
<h1>Title</h1>
<p>Content</p>
</div>
)
}
🧩 Interview-Style Q&A
Q: What's the difference between a React component and a regular JavaScript function? A: A React
component is a JavaScript function that returns JSX. The key difference is that React components describe
what the UI should look like, and React handles rendering and updating the DOM when data changes.
Q: Why do we use export default in React components? A: export default makes the component the
main export of the file, allowing other files to import it easily with import App from './App'. This is the
standard pattern for React components.
Q: What happens when you run npm run dev with Vite? A: Vite starts a development server that serves
your React application, enables hot module replacement (instant updates when you save files), and provides
fast refresh for a smooth development experience.
Question 2: What would happen if you removed the <div> wrapper in the App component and tried to
return multiple elements directly? Answer: You'd get a syntax error because JSX requires a single parent
element. React components must return a single JSX element (though it can contain multiple children).
Question 3: Why might you choose Vite over Create React App for a new project? Answer: Vite is significantly
faster for development builds, has better hot module replacement, uses modern ES modules, and starts up
much quicker than Create React App.
Question 4: In a MERN application, where would you typically make API calls to your Express backend?
Answer: API calls are typically made within React components using useEffect hooks, event handlers, or
custom hooks, allowing the frontend to fetch and send data to your Node.js/Express server.
7 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
The simple "Hello world" component you just created will evolve into complex UIs that seamlessly integrate
with your Node.js APIs and MongoDB data.
This section introduces React components as JavaScript functions that return JSX - this is the fundamental
building block of every React application you'll ever build. Understanding this deeply is crucial for your MERN
stack mastery.
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
8 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
Critical insight: The HTML file is mostly empty. React takes control of the <div id="root"> and renders
everything dynamically. This is called a Single Page Application (SPA).
Why arrow functions? They're concise, have predictable this binding (important for class components), and
are the modern JavaScript standard.
const b = 20
console.log(now, a+b)
return (
<div>
<p>Hello world, it is {now.toString()}</p>
<p>
{a} plus {b} is {a + b}
</p>
</div>
)
}
Key concept: Curly braces {} in JSX execute JavaScript expressions and embed the result into the HTML.
return (
<div className="dashboard">
<h1>Welcome, {user.name}</h1>
<p>Last login: {lastLogin.toLocaleDateString()}</p>
<p>You have {notifications.length} new notifications</p>
</div>
)
}
// Frontend component
const ProductList = () => {
const [products, setProducts] = useState([])
useEffect(() => {
// API call to your Express server
fetch('/api/products')
.then(res => res.json())
.then(data => setProducts(data))
}, [])
return (
<div>
10 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
{products.map(product => (
<div key={product._id}>
<h3>{product.name}</h3>
<p>${product.price}</p>
</div>
))}
</div>
)
}
// ✅ CORRECT
const App = () => (
<div>Hello</div>
)
export default App
11 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
return <div>Hello</div>
}
Important: Console logs in component body run on every render, not just once. This is crucial for debugging
performance issues.
Performance implication: Any expensive calculations in the component body will run on every render. This is
why React hooks like useMemo and useCallback exist.
12 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
🧩 Interview-Style Q&A
Q: What's the difference between {variable} and "variable" in JSX? A: {variable} evaluates the
JavaScript variable and embeds its value, while "variable" is just the literal string "variable". JSX uses curly
braces to switch from HTML-like syntax to JavaScript evaluation.
Q: Why do React components need to be exported? A: Components are just JavaScript functions in
separate files. Without export default, other files can't import and use the component, breaking the
modular architecture that makes React scalable.
Q: What happens if you put a complex API call directly in the component body? A: It would run on every
render, causing performance issues and potentially infinite loops. API calls should be in useEffect hooks or
event handlers, not the component body.
Q: How does React know when to update the DOM? A: React calls your component function whenever
state or props change, compares the new JSX with the previous version (virtual DOM diffing), and only
updates the parts of the actual DOM that changed.
Answer: "5 + 10 = 15" - Each curly brace evaluates its JavaScript expression independently.
13 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
)
// No export statement
Answer: Missing export default App - the component can't be imported by other files, breaking the
application.
Answer: Every time the component renders (initially and on every re-render due to state/prop changes).
Question 4: In a MERN application, where would you typically fetch data from your Express API? Answer: In a
useEffect hook, not in the component body, to avoid fetching on every render.
Question 5: What's the purpose of the <div id="root"> in index.html? Answer: It's the mounting point
where React injects all your component-generated DOM elements. React takes control of this element and
everything inside it.
The simple dynamic content examples here ({now.toString()}, {a + b}) are the same patterns you'll use to
display user names, product prices, order statuses, and any other dynamic data from your backend APIs.
Critical understanding: JSX is not HTML. It's a JavaScript syntax extension that gets compiled into
JavaScript function calls. This distinction is fundamental for understanding React's performance, debugging,
and advanced patterns.
return (
<div>
<p>Hello world, it is {now.toString()}</p>
<p>{a} plus {b} is {a + b}</p>
</div>
)
}
return React.createElement(
'div',
null,
React.createElement(
'p', null, 'Hello world, it is ', now.toString()
),
React.createElement(
'p', null, a, ' plus ', b, ' is ', a + b
)
)
}
Vite handles this automatically - when you save a .jsx file, Vite + Babel instantly transforms it and hot-
reloads your browser. This is why development feels so smooth.
15 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
Since you work with Java backends, this comparison will be valuable:
Key differences:
Thymeleaf: Server renders HTML with data, sends complete HTML to browser
JSX: Client-side JavaScript renders dynamic content in the browser
Performance: JSX enables faster subsequent updates since only changed parts re-render
return (
<div className="product-card">
<h3>{product.name}</h3>
<p className={isInStock ? 'in-stock' : 'out-of-stock'}>
{isInStock ? `$${discountPrice.toFixed(2)}` : 'Out of Stock'}
</p>
<p>Reviews: {product.reviews.length} ({product.avgRating}/5)</p>
{product.discount > 0 && (
<span className="discount">{(product.discount * 100).toFixed(0)}%
OFF</span>
)}
</div>
)
}
return (
16 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
<div className="metrics-dashboard">
<h2>System Status</h2>
<p>Last updated: {lastUpdated.toLocaleTimeString()}</p>
{metrics ? (
<div>
<p>CPU Usage: {metrics.cpu}%</p>
<p>Memory: {(metrics.memory / 1024 / 1024).toFixed(2)} MB</p>
<div className={`status ${metrics.healthy ? 'healthy' : 'error'}`}>
{metrics.healthy ? '✅ All Systems Operational' : '⚠ Issues
Detected'}
</div>
</div>
) : (
<p>Loading metrics...</p>
)}
</div>
)
}
Why this matters: JSX gets compiled to React.createElement() calls, which require properly structured
arguments. Unclosed tags break the compilation process.
// ✅ Wrapped in container
const WrappedElements = () => (
<div>
<h1>Title</h1>
17 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
<p>Content</p>
</div>
)
Why: class and for are JavaScript reserved words. JSX uses className and htmlFor instead.
}
return <p>Please log in</p>
}
return (
<div>
{renderUserStatus()}
</div>
)
}
// This JSX...
<div>
<ProductList products={products} />
<UserProfile user={currentUser} />
</div>
Performance insight: Every JSX element becomes a function call. Deeply nested JSX creates deeply nested
function calls, which can impact performance in large applications.
// Usage
const ProtectedDashboard = withAuth(Dashboard)
19 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
// In your app
<ProtectedDashboard user={currentUser} data={dashboardData} />
useEffect(() => {
fetch(url)
.then(res => res.json())
.then(data => {
setData(data)
setLoading(false)
})
}, [url])
🧩 Interview-Style Q&A
Q: What's the difference between JSX and HTML, and why does it matter for performance? A: JSX
compiles to JavaScript function calls (React.createElement), while HTML is static markup. This matters
because React can efficiently compare and update only changed parts of the virtual DOM, whereas HTML
requires full page reloads for updates.
Q: Why can't you use if statements directly in JSX, but ternary operators work? A: JSX expects
expressions (values that evaluate to something), not statements (code that performs actions). if is a
statement, while ternary (condition ? value1 : value2) is an expression that returns a value.
Q: How does JSX compilation affect bundle size and performance? A: JSX adds minimal overhead since it
compiles to efficient JavaScript. However, the Babel transformation does add to build time, and deeply nested
JSX can create many function calls, potentially affecting runtime performance in large applications.
20 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
Q: In a MERN application, how would you handle server-side data in JSX? A: You'd fetch data in
useEffect hooks or data fetching libraries, store it in component state, and use JSX expressions to render the
dynamic content. Unlike server-side templating, the data fetching happens client-side after initial page load.
// A
<img src="photo.jpg">
// B
<img src="photo.jpg" />
// C
<Img src="photo.jpg" />
Answer: B and C are valid. A is invalid because JSX requires self-closing tags to be properly closed. C is valid
assuming Img is a React component.
Answer: Missing key prop in the mapped elements. React needs unique keys for efficient list rendering: <div
key={user.id}>.
<p>Hello</p>
</div>
)
Answer: JSX uses className instead of class because class is a JavaScript reserved word.
// Approach A
{isLoggedIn && <Dashboard />}
// Approach B
{isLoggedIn ? <Dashboard /> : null}
Answer: Functionally identical. Both use conditional rendering and only create the Dashboard element when
needed. Approach A is slightly more concise.
Scalable Component Architecture: Understanding JSX compilation helps you design efficient component
hierarchies for large applications.
Performance Optimization: Knowing that JSX becomes function calls helps you optimize render cycles and
avoid unnecessary re-renders.
Debugging Complex UIs: When React errors occur, they often reference the compiled JavaScript, not your
JSX. Understanding this mapping helps debug faster.
Server-Side Rendering (SSR): JSX compilation knowledge is crucial when implementing Next.js or custom
SSR solutions in your MERN stack.
The seemingly simple JSX syntax is actually a sophisticated abstraction that enables React's powerful
declarative programming model while maintaining high performance through efficient compilation and virtual
DOM diffing.
✅ Core Objectives
Component Composition - The Heart of React Architecture
This section introduces component composition - the fundamental architectural pattern that makes React
scalable from simple apps to enterprise-level applications. Understanding this deeply is crucial for building
maintainable MERN stack applications.
// Component composition
const App = () => {
return (
<div>
<h1>Greetings</h1>
<Hello />
</div>
)
}
What's happening architecturally: React is building a component tree where App is the parent and Hello is
a child. Each component is responsible for its own piece of the UI, creating separation of concerns.
Critical insight: Each <Hello /> creates a separate instance of the Hello component. This means:
Each instance can have its own state (when we add state)
Each renders independently
23 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
return (
<div>
<Header />
<ProductCategory category="Electronics" products={electronics} />
<ProductCategory category="Laptops" products={laptops} />
<ProductCategory category="Phones" products={phones} />
<Footer />
</div>
)
}
24 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
System design benefit: This tree structure mirrors how you'd architect microservices - each component has a
single responsibility and clear boundaries.
useEffect(() => {
// Fetch from your Express API
Promise.all([
fetch(`/api/users/${userId}`),
fetch(`/api/users/${userId}/posts`)
])
.then(responses => Promise.all(responses.map(r => r.json())))
.then(([userData, postsData]) => {
setUser(userData)
setPosts(postsData)
})
}, [userId])
return (
<div className="user-profile">
<UserHeader user={user} />
<UserStats posts={posts} />
<PostsList posts={posts} />
</div>
)
}
return (
25 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
<article className="post-card">
<h3>{post.title}</h3>
<p>{post.content.substring(0, 200)}...</p>
<div className="post-meta">
<span>{timeAgo}</span>
<span>{post.likes} likes</span>
</div>
</article>
)
}
return (
<ProductList
products={filteredProducts}
loading={loading}
onFilterChange={setFilters}
/>
)
}
26 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
return (
<div>
<ProductFilters onFilterChange={onFilterChange} />
<div className="products-grid">
{products.map(product => (
<ProductCard key={product._id} product={product} />
))}
</div>
</div>
)
}
2. Composition vs Inheritance
React favors composition over inheritance. Instead of extending classes, you compose behavior:
27 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
// ✅ Appropriate granularity
const Button = ({ text, icon, onClick }) => (
<button onClick={onClick}>
{icon && <i className={icon} />}
<span>{text}</span>
</button>
)
<MainContent />
<Footer />
</Layout>
)
return (
<div>
<h1>Count: {count}</h1>
<button onClick={() => setCount(count + 1)}>Increment</button>
<Hello /> {/* This re-renders every time App re-renders */}
<ExpensiveComponent /> {/* This also re-renders unnecessarily */}
</div>
)
}
Performance issue: When count changes, ALL child components re-render, even if they don't use count.
Solutions:
return (
<div>
<h1>Count: {count}</h1>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
)
}
29 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
// Basic structure
const App = () => {
return (
<BrowserRouter> {/* Part 6 will show this wrapping */}
<AuthProvider>
<ThemeProvider>
<div className="app">
<Header />
<Routes>
<Route path="/" element={<Home />} />
<Route path="/profile" element={<Profile />} />
</Routes>
<Footer />
</div>
</ThemeProvider>
</AuthProvider>
</BrowserRouter>
)
}
Architecture insight: The App component often becomes a composition root where you wire together:
Routing logic
Global state providers
Authentication context
Theme providers
Error boundaries
🧩 Interview-Style Q&A
Q: How does React handle multiple instances of the same component in terms of performance and
memory? A: Each component instance is independent with its own state and lifecycle. React uses a virtual
DOM diffing algorithm to efficiently update only changed instances. Memory usage scales linearly with
instances, but React's reconciliation algorithm minimizes DOM operations.
Q: What's the difference between using a component multiple times versus using a map function? A:
Explicitly writing <Hello /> three times creates three static instances known at compile time. Using map
creates dynamic instances based on data, allowing for variable numbers of components and efficient list
updates with proper key props.
Q: In a large MERN application, how would you decide when to break a component into smaller
components? A: Break components when they have multiple responsibilities, become hard to test, exceed
~100-150 lines, or when parts could be reused elsewhere. Each component should have a single responsibility
and clear data dependencies.
30 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
Q: How does component composition relate to the concept of microservices in backend architecture?
A: Both follow single responsibility principles and clear boundaries. Components are like frontend
microservices - they're independently developed, tested, and can be composed to create larger functionality.
However, components share memory space unlike true microservices.
Answer: All child components re-render, including both Hello instances and DataDisplay, even though the
Hello components don't depend on data.
Answer: Missing key prop. Should be <UserCard key={user._id} user={user} /> for efficient React
reconciliation.
// Approach A
const App = () => (
<div>
<Hello />
<Hello />
<Hello />
</div>
)
// Approach B
const App = () => (
31 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
<div>
{[1, 2, 3].map(i => <Hello key={i} />)}
</div>
)
Answer: Approach A is slightly more performant as it avoids the array creation and map operation, though
both are very fast in practice.
Answer: Two paragraphs with "Hello". Both <Greeting></Greeting> and <Greeting /> are equivalent JSX
syntax for components without children.
Question 5: In a MERN stack, where would you typically place API calls in this component hierarchy?
Answer: In the individual components (UserProfile and PostsList) using useEffect hooks, or in a parent
component that passes data down as props, depending on whether the data is shared.
Scalable Frontend Architecture: Break complex UIs into manageable, testable components that teams can
develop independently.
32 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
Microservices Alignment: Component boundaries often align with backend service boundaries, creating
consistent system architecture.
Performance Optimization: Understanding component trees helps identify bottlenecks and optimize
rendering strategies.
Code Maintainability: Well-composed components are easier to debug, test, and modify as requirements
change.
Team Collaboration: Clear component boundaries enable multiple developers to work on different parts of
the application simultaneously.
The simple pattern of defining reusable components and composing them into larger functionality is the
foundation that enables React applications to scale from simple prototypes to enterprise-level systems serving
millions of users.
Props (short for "properties") are React's mechanism for passing data down the component tree. This is
fundamental to React's unidirectional data flow and is the primary way components communicate in a React
application.
33 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
Critical understanding: Props create a parent-child data contract. The parent component controls what
data flows down, while child components receive and render that data. This is React's version of dependency
injection.
return (
<div>
<h1>Greetings</h1>
<Hello name='Maya' age={26 + 10} /> {/* String literal + expression
*/}
<Hello name={name} age={age} /> {/* Variables */}
</div>
)
}
Key patterns:
34 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
return (
<div className="product-card">
<img src={product.imageUrl} alt={product.name} />
<h3>{product.name}</h3>
<p className="description">{product.description}</p>
<div className="pricing">
{discount > 0 ? (
<>
<span className="original-price">${product.price}</span>
<span className="discounted-price">${discountedPrice.toFixed(2)}
</span>
<span className="discount-badge">{(discount * 100)}% OFF</span>
</>
) : (
<span className="price">${product.price}</span>
)}
</div>
<div className="metadata">
<p>In Stock: {product.inventory}</p>
<p>Rating: {product.averageRating}/5 ({product.reviewCount} reviews)</p>
</div>
{canPurchase ? (
<button
onClick={() => onAddToCart(product._id)}
disabled={product.inventory === 0}
>
Add to Cart
</button>
) : (
<p className="login-prompt">Please log in to purchase</p>
)}
</div>
)
}
useEffect(() => {
// Fetch products from MongoDB via Express API
fetch('/api/products')
.then(res => res.json())
.then(setProducts)
.then(setCurrentUser)
}, [])
if (response.ok) {
// Update cart state, show success message, etc.
}
} catch (error) {
console.error('Failed to add to cart:', error)
}
}
return (
<div className="product-list">
<h2>Our Products</h2>
{flashSale.active && (
<div className="flash-sale-banner">
🔥 Flash Sale: {(flashSale.discount * 100)}% off all items!
</div>
)}
<div className="products-grid">
{products.map(product => (
<ProductCard
key={product._id}
product={product}
onAddToCart={handleAddToCart}
currentUser={currentUser}
discount={flashSale.active ? flashSale.discount : 0}
/>
))}
</div>
</div>
)
}
36 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
trend,
isLoading,
formatter = (val) => val,
thresholds = { warning: 70, critical: 90 }
} = props
return (
<div className={`metric-widget ${getStatus()}`}>
<h3>{title}</h3>
{isLoading ? (
<div className="loading-skeleton">Loading...</div>
) : (
<>
<div className="metric-value">
{formattedValue} {unit}
</div>
{trend && (
<div className={`trend ${trend.direction}`}>
{trend.direction === 'up' ? '↗' : '↘'}
{trend.percentage}% vs last month
</div>
)}
</>
)}
</div>
)
}
useEffect(() => {
// Fetch real-time metrics from your Express API
const fetchMetrics = async () => {
try {
const response = await fetch('/api/admin/metrics')
const data = await response.json()
setMetrics(data)
setIsLoading(false)
37 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
} catch (error) {
console.error('Failed to fetch metrics:', error)
}
}
fetchMetrics()
const interval = setInterval(fetchMetrics, 30000) // Update every 30 seconds
return (
<div className="admin-dashboard">
<h1>System Dashboard</h1>
<div className="metrics-grid">
<MetricWidget
title="Server Load"
value={metrics.serverLoad.value}
unit="%"
trend={metrics.serverLoad.trend}
isLoading={isLoading}
thresholds={{ warning: 70, critical: 90 }}
/>
<MetricWidget
title="Active Users"
value={metrics.activeUsers.value}
unit="users"
trend={metrics.activeUsers.trend}
isLoading={isLoading}
formatter={formatNumber}
/>
<MetricWidget
title="Monthly Revenue"
value={metrics.revenue.value}
unit=""
trend={metrics.revenue.trend}
isLoading={isLoading}
formatter={formatCurrency}
thresholds={{ warning: 50000, critical: 100000 }}
/>
</div>
</div>
)
}
38 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
return (
<button
className={`btn btn-${variant} btn-${size}`}
disabled={disabled}
onClick={onClick}
type={type}
>
39 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
{children}
</button>
)
}
useEffect(() => {
const checkHealth = async () => {
const startTime = performance.now()
try {
const response = await fetch(`/api/health${endpoint}`, { method })
const endTime = performance.now()
setStatus({
healthy: response.ok,
latency: Math.round(endTime - startTime)
})
setLastCheck(new Date())
} catch (error) {
setStatus({ healthy: false, latency: null })
setLastCheck(new Date())
}
}
checkHealth()
const intervalId = setInterval(checkHealth, interval)
40 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
return (
<div className="api-status-indicator">
<div className={`status-dot ${getStatusColor()}`}></div>
<span className="endpoint">{method} {endpoint}</span>
{status.latency && (
<span className="latency">({status.latency}ms)</span>
)}
{lastCheck && (
<span className="last-check">
Last checked: {lastCheck.toLocaleTimeString()}
</span>
)}
</div>
)
}
return <div>{props.user.name}</div>
}
return (
<div>
<p>{user.name}</p>
<button onClick={() => handleNameChange('New Name')}>
Update Name
</button>
</div>
)
}
41 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
// ❌ Wrong - using state for data that should come from props
const ProductCard = ({ productId }) => {
const [product, setProduct] = useState(null)
useEffect(() => {
fetch(`/api/products/${productId}`)
.then(res => res.json())
.then(setProduct)
}, [productId])
return (
<div>
<h3>{product.name}</h3>
<p>${product.price}</p>
</div>
)
}
useEffect(() => {
fetch('/api/products')
.then(res => res.json())
.then(products => {
setProducts(products)
setLoading(false)
})
}, [])
return (
<div>
{products.map(product => (
<ProductCard
key={product._id}
product={product}
isLoading={loading}
/>
))}
</div>
)
}
42 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
if (!shouldRender) {
console.log('Component not rendering due to conditions')
return null
}
// Parent component
const App = () => {
const [count, setCount] = useState(0)
const [user, setUser] = useState({ name: 'John', age: 30 })
return (
<div>
<button onClick={() => setCount(count + 1)}>
Count: {count}
</button>
{/* This component re-renders even when user/settings don't change */}
<UserProfile user={user} settings={userSettings} />
</div>
)
}
return (
<div>
<button onClick={() => setCount(count + 1)}>
Count: {count}
</button>
{/* This component only re-renders when user or settings actually change */}
<UserProfile
user={user}
settings={userSettings}
onUpdate={handleUserUpdate}
/>
</div>
)
}
return (
<div>
<h3>{user.name}</h3>
<p>Age: {user.age}</p>
<p>Theme: {settings.theme}</p>
</div>
)
})
🧩 Interview-Style Q&A
Q: What's the difference between props and state, and when should you use each? A: Props are external
data passed from parent to child (immutable within the component), while state is internal data managed by
the component itself (mutable). Use props for data that comes from parent components or APIs, use state for
data that changes over time within the component.
44 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
Q: How does React handle props passing in large component trees, and what are the performance
implications? A: React passes props down the component tree one level at a time. In deep trees, this can
cause "prop drilling" where intermediate components pass props they don't use. Performance impact includes
unnecessary re-renders and memory overhead. Solutions include Context API, state management libraries, or
component composition patterns.
Q: What happens if you mutate props directly, and why is it problematic? A: Mutating props breaks
React's immutability principle, can cause bugs where UI doesn't update when data changes, makes debugging
difficult, and can lead to unexpected side effects in parent components. React assumes props are immutable
for optimization purposes.
Q: In a MERN application, how would you structure props for a component that displays user data
from MongoDB? A: Structure props to separate data concerns: pass the user object, loading state, error state,
and callback functions separately. For example: <UserCard user={userData} isLoading={loading}
error={error} onEdit={handleEdit} onDelete={handleDelete} />. This makes the component more
testable and reusable.
Answer: It mutates props directly. Props should be treated as read-only. Should create a new variable: const
displayName = props.user.name.toUpperCase()
// A
<Hello name=name age=age />
// B
<Hello name={name} age={age} />
// C
<Hello name="name" age="age" />
Answer: B is correct. JavaScript variables and expressions must be wrapped in curly braces. A is invalid syntax,
C passes literal strings "name" and "age".
45 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
Answer: { message: "Hello", count: 42, isVisible: true } - an object containing all the props
passed to the component.
Answer: Use default parameters: const Button = ({ text, variant = 'primary' }) => { ... }
Answer: Every time App re-renders, because both user and theme objects are recreated on each render,
causing React.memo to see them as "different" props.
46 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
Scalable Component Architecture: Design reusable components that work with different data sets through
props interface design.
Efficient Data Flow: Structure your component hierarchy to minimize prop drilling and optimize data
distribution from your Express APIs.
Performance Optimization: Understanding props behavior helps identify and fix re-rendering issues in large
applications.
API Integration Patterns: Props facilitate clean separation between data-fetching logic (containers) and
presentation logic (components).
Testing and Debugging: Props provide clear interfaces that make components easier to test with different
data scenarios.
The ability to pass data through props transforms static components into dynamic, reusable building blocks
that can handle real-world data from your MongoDB database via Express API endpoints. This is the
foundation for building maintainable, scalable MERN applications.
What's happening: ESLint (a code quality tool) is warning that your component accepts props but doesn't
explicitly define what types those props should be. This is a best practice reminder, not a breaking error.
export default [
{ ignores: ['dist'] },
{
files: ['**/*.{js,jsx}'],
languageOptions: {
47 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
ecmaVersion: 2020,
globals: globals.browser,
parserOptions: {
ecmaVersion: 'latest',
ecmaFeatures: { jsx: true },
sourceType: 'module',
},
},
settings: { react: { version: '18.3' } },
plugins: {
react,
'react-hooks': reactHooks,
'react-refresh': reactRefresh,
},
rules: {
// ... other rules ...
'react/prop-types': 0, // This disables the prop-types warning
},
},
]
Static code analysis tool that catches potential bugs and enforces coding standards
Integrated into Vite automatically for React projects
Not a compiler - your code runs fine without fixing ESLint warnings
Development helper - improves code quality and team consistency
In modern React development, you have several options for prop validation:
Hello.propTypes = {
name: PropTypes.string.isRequired,
age: PropTypes.number.isRequired
}
Q2: Why might a team choose to keep prop-types validation enabled? A2: It catches bugs at
development time when components receive unexpected data types, especially helpful when integrating with
backend APIs that might return different data structures.
Q3: What does adding 'react/prop-types': 0 do? A3: It disables the ESLint rule that warns about
missing prop type validation, allowing you to use props without defining their expected types.
This is a common setup step you'll encounter in React development. Understanding that it's a tool
configuration (not a code problem) helps you focus on learning React concepts without being distracted by
tooling warnings!
49 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
Core principle: Never write more code when errors exist. This is crucial for scalable system development.
React component names MUST start with a capital letter. This distinguishes custom components from
HTML elements.
<div>
<h1>Greetings</h1>
<footer /> {/* Renders empty HTML footer tag */}
</div>
)
Why this matters: React's JSX compiler uses capitalization to differentiate between:
Valid Solutions
React Fragments (<>...</>) allow multiple elements without adding extra DOM nodes:
// DOM output:
// <div>
// <header>...</header>
// <main>...</main>
// <footer>...</footer>
// </div>
52 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
// DOM output:
// <header>...</header>
// <main>...</main>
// <footer>...</footer>
useEffect(() => {
console.log('Fetching user data for ID:', userId) // Debug API calls
fetch(`/api/users/${userId}`)
.then(response => {
console.log('API response status:', response.status)
return response.json()
})
.then(userData => {
console.log('User data received:', userData) // Debug API response
setUser(userData)
})
.catch(err => {
console.error('API error:', err) // Debug errors
setError(err.message)
})
}, [userId])
if (error) {
console.log('Rendering error state')
return <div className="error">Error: {error}</div>
}
if (!user) {
console.log('Rendering loading state')
return <LoadingSpinner />
}
53 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
)
}
static getDerivedStateFromError(error) {
console.error('Error boundary caught error:', error)
return { hasError: true, error }
}
componentDidCatch(error, errorInfo) {
console.error('Error boundary details:', error, errorInfo)
// In production, send to logging service
// logErrorToService(error, errorInfo)
}
render() {
if (this.state.hasError) {
return (
<div className="error-boundary">
<h2>Something went wrong</h2>
<p>Please refresh the page or try again later.</p>
{process.env.NODE_ENV === 'development' && (
<pre>{this.state.error.toString()}</pre>
)}
</div>
)
}
return this.props.children
}
}
// Usage
const App = () => (
<ErrorBoundary>
<Router>
<Header />
<Routes>
<Route path="/" element={<Home />} />
<Route path="/dashboard" element={<Dashboard />} />
</Routes>
</Router>
</ErrorBoundary>
)
54 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
55 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
A1: An empty HTML <header> element, not your component, because React components must be
capitalized.
A2: Multiple root elements without a wrapper. JSX requires a single parent element or Fragment.
// A
return <div><h1>Title</h1><p>Content</p></div>
// B
return <><h1>Title</h1><p>Content</p></>
A3: Approach A creates an extra <div> wrapper in the DOM, while approach B renders only the <h1> and <p>
elements directly.
Q4: When should you stop coding and debug? A4: Immediately when any error appears in the console.
Never write more code when errors exist.
This disciplined approach to React development directly translates to building robust, maintainable MERN
applications that can scale to handle real-world complexity!
✅ Core Objectives
Understanding React's Rendering Limitations
This section addresses one of the most common beginner errors in React development - attempting to
render objects directly in JSX. Understanding this deeply prevents countless debugging sessions and builds a
solid foundation for complex data rendering patterns you'll use throughout your MERN stack development.
return (
<div>
<p>{friends[0]}</p> {/* Tries to render: { name: 'Peter', age: 4 } */}
<p>{friends[1]}</p> {/* Tries to render: { name: 'Maya', age: 10 } */}
</div>
)
}
Root cause: React can only render primitive values (strings, numbers, booleans) and valid React elements.
JavaScript objects don't have a default visual representation that React can understand.
57 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
</div>
)
return (
<div>
<p>{friends[0].name} {friends[0].age}</p> {/* "Peter 4" */}
<p>{friends[1].name} {friends[1].age}</p> {/* "Maya 10" */}
</div>
)
}
Key insight: You render the primitive values inside the object, not the object itself.
useEffect(() => {
fetch('/api/products/123')
.then(res => res.json())
.then(productData => {
console.log('Product data from MongoDB:', productData)
setProduct(productData)
})
}, [])
return (
<div className="product-card">
{/* ❌ This would break if you tried to render the whole product object */}
{/* <p>{product}</p> */}
<p>Category: {product.category}</p>
<p>In Stock: {product.inventory}</p>
useEffect(() => {
// Fetch user data from Express API
fetch('/api/users/me')
.then(res => res.json())
.then(data => {
console.log('User data structure:', data)
// Typical MongoDB user document:
// {
// _id: "...",
// name: "John Doe",
// email: "john@example.com",
// profile: {
// avatar: "...",
// bio: "...",
// location: "..."
// },
// preferences: {
// theme: "dark",
// notifications: true
// },
// orderHistory: [...],
// createdAt: "2024-01-01T...",
// }
setUserData(data)
59 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
})
}, [])
return (
<div className="user-dashboard">
{/* ❌ Never do this */}
{/* <div>{userData}</div> */}
60 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
useEffect(() => {
fetch('/api/analytics/dashboard')
.then(res => res.json())
.then(data => {
// CRITICAL: Always log API responses to understand structure
console.log('API Response Structure:', data)
console.log('Type of response:', typeof data)
console.log('Is it an array?', Array.isArray(data))
// If you tried to render this directly, you'd get the object error
// <p>{data}</p> // ❌ Would break
setApiData(data)
})
.catch(err => {
console.error('API Error:', err)
setError(err.message)
})
}, [])
return (
<div className="analytics-dashboard">
{/* ✅ Safely render object properties */}
<div className="metrics">
<div className="metric">
<h3>Total Users</h3>
<p>{apiData.metrics.totalUsers.toLocaleString()}</p>
</div>
<div className="metric">
<h3>Revenue</h3>
<p>${apiData.metrics.revenue.toLocaleString()}</p>
</div>
<div className="metric">
<h3>Growth</h3>
<p>{apiData.metrics.growth}%</p>
</div>
</div>
61 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
<div key={product.id}>
<span>{product.name}</span>
<span>{product.sales} sales</span>
</div>
))}
</div>
</div>
)
}
return (
<div className="user-info">
<p><strong>Name:</strong> {user.name}</p>
<p><strong>Email:</strong> {user.email}</p>
<p><strong>Role:</strong> {user.role}</p>
{user.lastLogin && (
<p><strong>Last Login:</strong> {new
Date(user.lastLogin).toLocaleString()}</p>
)}
</div>
)
}
return (
<div>
{/* Your normal component rendering */}
<h1>{data.title}</h1>
<p>{data.description}</p>
{isDevelopment && (
<details className="debug-panel">
<summary>Debug Data Structure</summary>
<pre>{JSON.stringify(data, null, 2)}</pre>
</details>
)}
</div>
)
}
return (
<div>
<img src={profileImage} alt="Profile" />
<p>{bio}</p>
<p>Location: {city}</p>
</div>
)
}
return (
<div>
{/* ✅ Arrays of primitives render as concatenated string */}
<p>{strings}</p> {/* Renders: "HelloWorld" */}
63 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
return (
<div>
{/* Step 4: Use safe property access */}
<h1>{apiResponse.user?.name || 'Unknown User'}</h1>
64 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
3. Performance Implications
return (
<div>
<p>{processedData.formattedDate}</p>
<p>{processedData.upperCaseName}</p>
</div>
)
}
return (
<div>
<p>{processedData.formattedDate}</p>
<p>{processedData.upperCaseName}</p>
</div>
)
}
static getDerivedStateFromError(error) {
// Check if it's the specific "objects are not valid" error
if (error.message.includes('Objects are not valid as a React child')) {
return {
hasError: true,
errorType: 'INVALID_OBJECT_RENDER',
65 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
componentDidCatch(error, errorInfo) {
console.error('Object rendering error:', error)
console.error('Error info:', errorInfo)
render() {
if (this.state.hasError) {
if (this.state.errorType === 'INVALID_OBJECT_RENDER') {
return (
<div className="error-fallback">
<h2>Data Display Error</h2>
<p>There was an issue displaying some data. Please refresh the page.
</p>
{process.env.NODE_ENV === 'development' && (
<p><em>Dev note: Check console for object rendering issues</em></p>
)}
</div>
)
}
}
return this.props.children
}
}
🧩 Interview-Style Q&A
Q: Why does React throw an error when trying to render objects, but allows arrays in some cases? A:
React can't determine how to visually represent arbitrary JavaScript objects - they have no inherent display
format. Arrays of primitives get concatenated into strings (which React can render), but arrays containing
objects still cause the same error. React needs explicit instructions on how to transform objects into
renderable content.
Q: How would you handle dynamic object properties from an API response where you don't know the
structure ahead of time? A: Use Object.entries() to iterate over unknown properties:
Object.entries(apiData).map(([key, value]) => <p key={key}>{key}: {String(value)}</p>).
Always convert values to strings and handle nested objects recursively or use JSON.stringify() for
debugging.
66 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
Q: What's the performance impact of frequently accessing deep object properties in JSX? A: Each
property access (like user.profile.settings.theme) is recalculated on every render. For deeply nested or
frequently accessed properties, use useMemo to cache the extracted values or destructure them once at the
component's top level.
Q: In a MERN application, how would you prevent object rendering errors when API responses have
inconsistent structures? A: Implement data validation/transformation layers: use libraries like Joi or Zod to
validate API responses, create data transformation functions that normalize responses, implement proper
loading/error states, and use TypeScript for compile-time safety on expected object structures.
Answer: Trying to render the entire user object. Fix: <div>{user.name} - {user.email}</div> (render
specific properties).
// A
<p>{["Hello", "World"]}</p>
// B
<p>{[{name: "John"}, {name: "Jane"}]}</p>
// C
<p>{42}</p>
Answer: A and C will render. A renders as "HelloWorld", C renders as "42". B throws an error because it's an
array of objects.
Answer: "AliceBob - Total: 2" (the array gets concatenated into a string).
Question 4: How would you safely render this potentially undefined nested property?
67 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
Question 5: What's the best practice for debugging object rendering errors? Answer: Always use
console.log() to inspect the data structure before rendering, check for undefined/null values, and use
browser developer tools to examine the actual data types and structures.
Robust API Integration: Handle complex MongoDB documents and Express API responses safely without
rendering errors.
Performance Optimization: Understand when object property access patterns impact rendering performance
and how to optimize them.
Error Prevention: Build defensive rendering patterns that gracefully handle incomplete or malformed data
from external APIs.
Debugging Efficiency: Quickly identify and resolve object rendering issues in complex component
hierarchies.
Production Reliability: Implement error boundaries and fallback mechanisms that prevent entire application
crashes due to data structure issues.
The "Objects are not valid as a React child" error is one of the most common stumbling blocks in React
development, especially when integrating with backend APIs. Mastering this concept ensures your MERN
applications handle real-world data robustly and maintain excellent user experiences even when encountering
unexpected data structures.
Explain the reasoning behind this change: What problem are we solving? Why use this structure or pattern?
Provide only the code for this step (clean, accurate, and following modern best practices).
List the key concepts or skills I'm learning in this step (e.g., props, component reuse, JSX, event handling).
Suggest a Git commit message that: Describes what was done in the step. Includes concepts learned in
parentheses — e.g., feat: split App into Header, Content, Total components and passed data via props (props,
component structure, JSX rendering)
🏁 At the End, Provide: 🔍 IMPORTANT: When providing the final code, include the ✅ full working code of
the final state (e.g., App.jsx or the full src/ folder if needed) — with detailed inline comments that explain
everything, line by line or block by block. ➡ Make sure each component, prop, state, function, or logic is
clearly explained — assume I’m learning and need help understanding every part. 📌 Summary of all Git
commit messages so I can track project history clearly. 🧠 List of all key MERN/React concepts covered across
the full assignment. ⚠ Common mistakes or beginner pitfalls (e.g., forgetting export default, improper prop
usage, missing keys in lists). 📘 Here’s the assignment to begin with:
Exercises 1.1.-1.2. The exercises are submitted via GitHub, and by marking the exercises as done in the "my
submissions" tab of the submission application.
The exercises are submitted one part at a time. When you have submitted the exercises for a part of the
course you can no longer submit undone exercises for the same part.
Note that in this part, there are more exercises besides those found below. Do not submit your work until you
have completed all of the exercises you want to submit for the part.
You may submit all the exercises of this course into the same repository, or use multiple repositories. If you
submit exercises of different parts into the same repository, please use a sensible naming scheme for the
directories.
One very functional file structure for the submission repository is as follows:
part0 part1 courseinfo unicafe anecdotes part2 phonebook countriescopy See this example submission
repository!
For each part of the course, there is a directory, which further branches into directories containing a series of
exercises, like "unicafe" for part 1.
69 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
Most of the exercises of the course build a larger application, eg. courseinfo, unicafe and anecdotes in this
part, bit by bit. It is enough to submit the completed application. You can make a commit after each exercise,
but that is not compulsory. For example the course info app is built in exercises 1.1.-1.5. It is just the end result
after 1.5 that you need to submit!
For each web application for a series of exercises, it is recommended to submit all files relating to that
application, except for the directory node_modules.
1.1: Course Information, step 1 The application that we will start working on in this exercise will be further
developed in a few of the following exercises. In this and other upcoming exercise sets in this course, it is
enough to only submit the final state of the application. If desired, you may also create a commit for each
exercise of the series, but this is entirely optional.
Use Vite to initialize a new application. Modify main.jsx to match the following
const App = () => { const course = 'Half Stack application development' const part1 = 'Fundamentals of
React' const exercises1 = 10 const part2 = 'Using props to pass data' const exercises2 = 7 const part3 = 'State
of a component' const exercises3 = 14
return (
{course}
{part1} {exercises1}
{part2} {exercises2}
{part3} {exercises3}
)}
export default Appcopy and remove the extra files App.css and index.css, also remove the directory assets.
Unfortunately, the entire application is in the same component. Refactor the code so that it consists of three
new components: Header, Content, and Total. All data still resides in the App component, which passes the
necessary data to each component using props. Header takes care of rendering the name of the course,
Content renders the parts and their number of exercises and Total renders the total number of exercises.
70 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
return (
) }copy WARNING Don't try to program all the components concurrently, because that will almost certainly
break down the whole app. Proceed in small steps, first make e.g. the component Header and only when it
works for sure, you could proceed to the next component.
Careful, small-step progress may seem slow, but it is actually by far the fastest way to progress. Famous
software developer Robert "Uncle Bob" Martin has stated
that is, according to Martin, careful progress with small steps is even the only way to be fast.
1.2: Course Information, step 2 Refactor the Content component so that it does not render any names of parts
or their number of exercises by itself. Instead, it only renders three Part components of which each renders the
name and number of exercises of one part.
) }copy Our application passes on information in quite a primitive way at the moment, since it is based on
individual variables. We shall fix that in part 2, but before that, let's go to part1b to learn about JavaScript.
I'll help you implement this step by step, following the structured approach you requested. Let's start with
Exercise 1.1.
71 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
App.jsx:
return (
<div>
{/* Course title using JSX expression */}
<h1>{course}</h1>
{/* Each part rendered with name and exercise count */}
<p>
{part1} {exercises1}
</p>
<p>
{part2} {exercises2}
</p>
<p>
{part3} {exercises3}
</p>
feat: create initial course info app with hardcoded data (JSX expressions,
component basics, JavaScript in JSX)
72 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
return (
<div>
{/* Pass course data to Header component via props */}
<Header course={course} />
<p>
{part1} {exercises1}
</p>
<p>
{part2} {exercises2}
</p>
73 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
<p>
{part3} {exercises3}
</p>
<p>Number of exercises {exercises1 + exercises2 + exercises3}</p>
</div>
)
}
feat: extract Header component and pass course title via props (props, component
separation, data flow)
74 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
)
}
return (
<p>Number of exercises {totalExercises}</p>
)
}
return (
<div>
<Header course={course} />
<p>
{part1} {exercises1}
</p>
<p>
{part2} {exercises2}
</p>
<p>
{part3} {exercises3}
</p>
75 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
feat: extract Total component with exercise calculation logic (multiple props,
component logic, calculations)
return (
<div>
{/* Render each part with its exercise count */}
<p>
{props.part1} {props.exercises1}
</p>
<p>
{props.part2} {props.exercises2}
</p>
<p>
{props.part3} {props.exercises3}
76 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
</p>
</div>
)
}
return (
<p>Number of exercises {totalExercises}</p>
)
}
return (
<div>
<Header course={course} />
77 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
feat: extract Content component to handle all course parts rendering (component
organization, props grouping)
return (
<p>
{props.name} {props.exercises}
</p>
)
}
78 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
return (
<p>Number of exercises {totalExercises}</p>
)
}
return (
<div>
<Header course={course} />
<Content
part1={part1}
exercises1={exercises1}
part2={part2}
exercises2={exercises2}
part3={part3}
exercises3={exercises3}
/>
feat: refactor Content to use individual Part components for better reusability
(component composition, reusable components)
🏁 Final Implementation
✅ Complete Working Code with Detailed Comments:
main.jsx:
App.jsx:
// Part Component - Displays a single course part with its exercise count
// Props: { name: string, exercises: number }
// Responsibility: Render one course part's information
// This component is reusable - we create 3 instances in Content
const Part = (props) => {
return (
<p>
{props.name} {props.exercises}
</p>
)
}
80 / 83
FullStackOpen Part 1 a Introduction to React.md 2025-08-08
return (
<p>Number of exercises {totalExercises}</p>
)
}
// App Component - Root component that manages all data and coordinates child
components
// Responsibility:
// 1. Store all course data (acts as single source of truth)
// 2. Pass appropriate data to each child component via props
// 3. Define the overall structure/layout of the application
const App = () => {
// All course data defined in the root component
// This creates a "single source of truth" for the application data
const course = 'Half Stack application development'
const part1 = 'Fundamentals of React'
const exercises1 = 10
const part2 = 'Using props to pass data'
const exercises2 = 7
const part3 = 'State of a component'
const exercises3 = 14
return (
<div>
{/* Component composition: App renders child components and passes data via
props */}
part1={part1}
exercises1={exercises1}
part2={part2}
exercises2={exercises2}
part3={part3}
exercises3={exercises3}
/>
1. feat: create initial course info app with hardcoded data (JSX expressions,
component basics, JavaScript in JSX)
2. feat: extract Header component and pass course title via props (props,
component separation, data flow)
3. feat: extract Total component with exercise calculation logic (multiple props,
component logic, calculations)
4. feat: extract Content component to handle all course parts rendering (component
organization, props grouping)
5. feat: refactor Content to use individual Part components for better reusability
(component composition, reusable components)
This foundation prepares you for building complex, data-driven MERN applications where components will
receive data from MongoDB via Express APIs and update dynamically based on user interactions!
83 / 83