Learn React fundamentals including JSX syntax, components, props, and React developer tools. Start your React journey with this comprehensive module.
Learn React fundamentals including JSX syntax, components, props, and React developer tools. Start your React journey with this comprehensive module.
Learn the core concepts of React and understand why it's the most popular frontend library
Content by: Praveen Kumar
MERN Stack Developer
React is a JavaScript library for building user interfaces, particularly single-page applications. It's used for handling the view layer and can be used for developing both web and mobile applications.
// React - Component-based approach
function Welcome(props) {
return <h1>Hello, {props.name}!</h1>;
}
// Angular - Template-based approach
@Component({
selector: 'app-welcome',
template: '<h1>Hello, {{name}}!</h1>'
})
export class WelcomeComponent {
@Input() name: string;
}
// Vue.js - Template-based approach
<template>
<h1>Hello, {{ name }}!</h1>
</template>
<script>
export default {
props: ['name']
}
</script>
// Create React App (CRA)
npx create-react-app my-react-app
cd my-react-app
npm start
// Vite (Modern alternative)
npm create vite@latest my-react-app -- --template react
cd my-react-app
npm install
npm run dev
// Next.js (Full-stack React)
npx create-next-app@latest my-next-app
cd my-next-app
npm run dev
// Project Structure
my-react-app/
āāā public/
ā āāā index.html
ā āāā favicon.ico
āāā src/
ā āāā App.js
ā āāā index.js
ā āāā components/
āāā package.json
āāā README.md
// Basic App.js
import React from 'react';
import './App.css';
function App() {
return (
<div className="App">
<header className="App-header">
<h1>Welcome to React</h1>
<p>Start building amazing applications!</p>
</header>
</div>
);
}
export default App;
// Exercise: Create a React Project
// 1. Set up a new React project
npx create-react-app todo-app
cd todo-app
// 2. Create a simple component
// src/components/TodoList.js
import React from 'react';
function TodoList() {
const todos = [
{ id: 1, text: 'Learn React', completed: false },
{ id: 2, text: 'Build a project', completed: false },
{ id: 3, text: 'Deploy to production', completed: false }
];
return (
<div className="todo-list">
<h2>My Todo List</h2>
<ul>
{todos.map(todo => (
<li key={todo.id}>
<input
type="checkbox"
checked={todo.completed}
onChange={() => console.log('Toggle todo')}
/>
<span style={{
textDecoration: todo.completed ? 'line-through' : 'none'
}}>
{todo.text}
</span>
</li>
))}
</ul>
</div>
);
}
export default TodoList;
// 3. Update App.js
import React from 'react';
import TodoList from './components/TodoList';
import './App.css';
function App() {
return (
<div className="App">
<header className="App-header">
<h1>React Todo App</h1>
</header>
<main>
<TodoList />
</main>
</div>
);
}
export default App;
// 4. Add some basic styling
// src/App.css
.App {
text-align: center;
padding: 20px;
}
.todo-list {
max-width: 500px;
margin: 0 auto;
text-align: left;
}
.todo-list ul {
list-style: none;
padding: 0;
}
.todo-list li {
padding: 10px;
border-bottom: 1px solid #eee;
display: flex;
align-items: center;
gap: 10px;
}
// 5. Run the application
npm start
// Challenge: Add a form to create new todos
// Challenge: Add functionality to delete todos
// Challenge: Add local storage to persist todos
Test your understanding of this topic:
Master JSX syntax to write clean and readable React components
Content by: Darshit Dobariya
MERN Stack Developer
JSX (JavaScript XML) is a syntax extension for JavaScript that allows you to write HTML-like code in your JavaScript files. It makes React components more readable and easier to write.
// Basic JSX element
const element = <h1>Hello, World!</h1>;
// JSX with JavaScript expressions
const user = {
name: 'John',
age: 30
};
const greeting = <h1>Hello, {user.name}!</h1>;
// JSX with attributes
const element = <div className="container">Content</div>;
// JSX with children
const element = (
<div>
<h1>Title</h1>
<p>Paragraph</p>
</div>
);
// Conditional rendering with ternary operator
function Greeting({ isLoggedIn }) {
return (
<div>
{isLoggedIn ? (
<h1>Welcome back!</h1>
) : (
<h1>Please sign in.</h1>
)}
</div>
);
}
// Conditional rendering with logical AND
function Mailbox({ unreadMessages }) {
return (
<div>
<h1>Hello!</h1>
{unreadMessages.length > 0 && (
<h2>You have {unreadMessages.length} unread messages.</h2>
)}
</div>
);
}
// Conditional rendering with variables
function LoginButton({ isLoggedIn }) {
let button;
if (isLoggedIn) {
button = <LogoutButton />;
} else {
button = <LoginButton />;
}
return <div>{button}</div>;
}
// JSX with arrays and mapping
function UserList({ users }) {
return (
<div>
<h2>User List</h2>
<ul>
{users.map(user => (
<li key={user.id}>
<strong>{user.name}</strong> - {user.email}
</li>
))}
</ul>
</div>
);
}
// JSX with fragments
function UserProfile({ user }) {
return (
<>
<h1>{user.name}</h1>
<p>{user.email}</p>
<p>{user.bio}</p>
</>
);
}
// JSX with event handlers
function Button({ onClick, children }) {
return (
<button
onClick={onClick}
className="btn btn-primary"
style={{ padding: '10px 20px' }}
>
{children}
</button>
);
}
// JSX with dynamic attributes
function DynamicElement({ tag, children, ...props }) {
const Tag = tag;
return <Tag {...props}>{children}</Tag>;
}
// Usage
<DynamicElement tag="h1" className="title">Dynamic Title</DynamicElement>
<DynamicElement tag="p" style={{ color: 'blue' }}>Dynamic paragraph</DynamicElement>
// Exercise: Build a Product Card Component
// Create a reusable product card component using JSX
// src/components/ProductCard.js
import React from 'react';
function ProductCard({ product }) {
const { name, price, image, rating, inStock } = product;
return (
<div className="product-card">
<img src={image} alt={name} className="product-image" />
<div className="product-info">
<h3>{name}</h3>
<p className="price">{price}</p>
<div className="rating">
{[...Array(5)].map((_, index) => (
<span
key={index}
className={index < rating ? 'star filled' : 'star'}
>
ā
</span>
))}
<span className="rating-text">({rating}/5)</span>
</div>
<div className="stock-status">
{inStock ? (
<span className="in-stock">In Stock</span>
) : (
<span className="out-of-stock">Out of Stock</span>
)}
</div>
<button
className="add-to-cart"
disabled={!inStock}
>
{inStock ? 'Add to Cart' : 'Sold Out'}
</button>
</div>
</div>
);
}
// Usage in App.js
const products = [
{
id: 1,
name: "Wireless Headphones",
price: 99.99,
image: "/images/headphones.jpg",
rating: 4,
inStock: true
},
{
id: 2,
name: "Smart Watch",
price: 199.99,
image: "/images/smartwatch.jpg",
rating: 5,
inStock: false
}
];
function App() {
return (
<div className="App">
<h1>Product Catalog</h1>
<div className="products-grid">
{products.map(product => (
<ProductCard key={product.id} product={product} />
))}
</div>
</div>
);
}
// Challenge: Add a search filter
// Challenge: Add sorting by price or rating
// Challenge: Add a shopping cart functionality
Test your understanding of this topic:
Learn to create and use React components effectively
Content by: Harsh Patel
MERN Stack Developer
Components are the building blocks of React applications. They let you split the UI into independent, reusable pieces, and think about each piece in isolation.
// Simple function component
function Welcome(props) {
return <h1>Hello, {props.name}!</h1>;
}
// Function component with destructuring
function Welcome({ name, age }) {
return (
<div>
<h1>Hello, {name}!</h1>
<p>You are {age} years old.</p>
</div>
);
}
// Function component with default props
function Welcome({ name = 'Guest', age = 0 }) {
return (
<div>
<h1>Hello, {name}!</h1>
<p>You are {age} years old.</p>
</div>
);
}
// Arrow function component
const Welcome = (props) => {
return <h1>Hello, {props.name}!</h1>;
};
// Class component
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}!</h1>;
}
}
// Class component with constructor
class Welcome extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
}
render() {
return (
<div>
<h1>Hello, {this.props.name}!</h1>
<p>Count: {this.state.count}</p>
</div>
);
}
}
// Component composition example
function Header({ title }) {
return <header className="app-header">{title}</header>;
}
function Sidebar({ children }) {
return <aside className="sidebar">{children}</aside>;
}
function Main({ children }) {
return <main className="main-content">{children}</main>;
}
function Footer({ text }) {
return <footer className="app-footer">{text}</footer>;
}
// Composing components
function App() {
return (
<div className="app">
<Header title="My React App" />
<div className="app-body">
<Sidebar>
<nav>
<ul>
<li>Home</li>
<li>About</li>
<li>Contact</li>
</ul>
</nav>
</Sidebar>
<Main>
<h1>Welcome to React</h1>
<p>This is the main content area.</p>
</Main>
</div>
<Footer text="Ā© 2025 My React App" />
</div>
);
}
// Higher-Order Component (HOC)
function withLoading(WrappedComponent) {
return function WithLoadingComponent({ isLoading, ...props }) {
if (isLoading) {
return <div>Loading...</div>;
}
return <WrappedComponent {...props} />;
};
}
// Usage
const UserListWithLoading = withLoading(UserList);
<UserListWithLoading isLoading={true} users={[]} />
// Exercise: Build a Blog Post Component System
// Create a modular blog system with reusable components
// src/components/BlogPost.js
import React from 'react';
function BlogPost({ post }) {
const { title, author, date, content, tags } = post;
return (
<article className="blog-post">
<BlogHeader title={title} author={author} date={date} />
<BlogContent content={content} />
<BlogFooter tags={tags} />
</article>
);
}
function BlogHeader({ title, author, date }) {
return (
<header className="blog-header">
<h1>{title}</h1>
<div className="blog-meta">
<span>By {author}</span>
<span>{new Date(date).toLocaleDateString()}</span>
</div>
</header>
);
}
function BlogContent({ content }) {
return (
<div className="blog-content">
{content.map((paragraph, index) => (
<p key={index}>{paragraph}</p>
))}
</div>
);
}
function BlogFooter({ tags }) {
return (
<footer className="blog-footer">
<div className="tags">
{tags.map(tag => (
<span key={tag} className="tag">
#{tag}
</span>
))}
</div>
</footer>
);
}
// Usage
const samplePost = {
title: "Getting Started with React",
author: "John Doe",
date: "2025-01-15",
content: [
"React is a powerful library for building user interfaces.",
"It uses a component-based architecture that makes code reusable and maintainable.",
"In this post, we'll explore the fundamentals of React development."
],
tags: ["react", "javascript", "frontend", "web-development"]
};
function App() {
return (
<div className="App">
<BlogPost post={samplePost} />
</div>
);
}
// Challenge: Add a comment system
// Challenge: Add a like/dislike functionality
// Challenge: Add a related posts section
Test your understanding of this topic:
Master React's data flow with props and state management
Content by: Shrungi Sangani
MERN Stack Developer
Props (properties) are a way to pass data from parent to child components. They are read-only and help make components reusable and configurable.
// Passing props to component
function Welcome(props) {
return <h1>Hello, {props.name}!</h1>;
}
// Using the component
<Welcome name="John" />
// Destructuring props
function Welcome({ name, age, city }) {
return (
<div>
<h1>Hello, {name}!</h1>
<p>Age: {age}</p>
<p>City: {city}</p>
</div>
);
}
// Using with destructured props
<Welcome name="John" age={25} city="New York" />
// Props with children
function Container({ children }) {
return <div className="container">{children}</div>;
}
<Container>
<h1>This is a child</h1>
<p>This is another child</p>
</Container>
// Using useState hook (Function Component)
import React, { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>
Increment
</button>
<button onClick={() => setCount(count - 1)}>
Decrement
</button>
</div>
);
}
// Class component with state
class Counter extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
}
increment = () => {
this.setState({ count: this.state.count + 1 });
}
decrement = () => {
this.setState({ count: this.state.count - 1 });
}
render() {
return (
<div>
<p>Count: {this.state.count}</p>
<button onClick={this.increment}>Increment</button>
<button onClick={this.decrement}>Decrement</button>
</div>
);
}
}
// Props with default values
function Button({
children,
variant = 'primary',
size = 'medium',
disabled = false,
onClick
}) {
const className = `btn btn-${variant} btn-${size}`;
return (
<button
className={className}
disabled={disabled}
onClick={onClick}
>
{children}
</button>
);
}
// Props validation with PropTypes
import PropTypes from 'prop-types';
function UserCard({ user, onEdit, onDelete }) {
return (
<div className="user-card">
<h3>{user.name}</h3>
<p>{user.email}</p>
<div className="actions">
<button onClick={() => onEdit(user.id)}>Edit</button>
<button onClick={() => onDelete(user.id)}>Delete</button>
</div>
</div>
);
}
UserCard.propTypes = {
user: PropTypes.shape({
id: PropTypes.number.isRequired,
name: PropTypes.string.isRequired,
email: PropTypes.string.isRequired
}).isRequired,
onEdit: PropTypes.func.isRequired,
onDelete: PropTypes.func.isRequired
};
// Props spreading
function FormField({ label, ...inputProps }) {
return (
<div className="form-field">
<label>{label}</label>
<input {...inputProps} />
</div>
);
}
// Usage
<FormField
label="Email"
type="email"
placeholder="Enter your email"
required
/>
// Complex state with objects
function UserProfile() {
const [user, setUser] = useState({
name: '',
email: '',
preferences: {
theme: 'light',
notifications: true
}
});
const updateUser = (field, value) => {
setUser(prev => ({
...prev,
[field]: value
}));
};
const updatePreference = (key, value) => {
setUser(prev => ({
...prev,
preferences: {
...prev.preferences,
[key]: value
}
}));
};
return (
<div>
<input
value={user.name}
onChange={(e) => updateUser('name', e.target.value)}
placeholder="Name"
/>
<input
value={user.email}
onChange={(e) => updateUser('email', e.target.value)}
placeholder="Email"
/>
<select
value={user.preferences.theme}
onChange={(e) => updatePreference('theme', e.target.value)}
>
<option value="light">Light</option>
<option value="dark">Dark</option>
</select>
</div>
);
}
// State with arrays
function TodoList() {
const [todos, setTodos] = useState([]);
const [newTodo, setNewTodo] = useState('');
const addTodo = () => {
if (newTodo.trim()) {
setTodos(prev => [...prev, {
id: Date.now(),
text: newTodo,
completed: false
}]);
setNewTodo('');
}
};
const toggleTodo = (id) => {
setTodos(prev => prev.map(todo =>
todo.id === id
? { ...todo, completed: !todo.completed }
: todo
));
};
const deleteTodo = (id) => {
setTodos(prev => prev.filter(todo => todo.id !== id));
};
return (
<div>
<input
value={newTodo}
onChange={(e) => setNewTodo(e.target.value)}
placeholder="Add new todo"
/>
<button onClick={addTodo}>Add</button>
<ul>
{todos.map(todo => (
<li key={todo.id}>
<input
type="checkbox"
checked={todo.completed}
onChange={() => toggleTodo(todo.id)}
/>
<span style={{
textDecoration: todo.completed ? 'line-through' : 'none'
}}>
{todo.text}
</span>
<button onClick={() => deleteTodo(todo.id)}>Delete</button>
</li>
))}
</ul>
</div>
);
}
// Exercise: Build a Shopping Cart
// Create a shopping cart with state management
// src/components/ShoppingCart.js
import React, { useState } from 'react';
function ShoppingCart() {
const [cart, setCart] = useState([]);
const [products] = useState([
{ id: 1, name: 'Laptop', price: 999, stock: 5 },
{ id: 2, name: 'Mouse', price: 25, stock: 10 },
{ id: 3, name: 'Keyboard', price: 75, stock: 8 }
]);
const addToCart = (product) => {
setCart(prev => {
const existingItem = prev.find(item => item.id === product.id);
if (existingItem) {
return prev.map(item =>
item.id === product.id
? { ...item, quantity: item.quantity + 1 }
: item
);
} else {
return [...prev, { ...product, quantity: 1 }];
}
});
};
const removeFromCart = (productId) => {
setCart(prev => prev.filter(item => item.id !== productId));
};
const updateQuantity = (productId, newQuantity) => {
if (newQuantity <= 0) {
removeFromCart(productId);
} else {
setCart(prev => prev.map(item =>
item.id === productId
? { ...item, quantity: newQuantity }
: item
));
}
};
const getTotalPrice = () => {
return cart.reduce((total, item) => total + (item.price * item.quantity), 0);
};
return (
<div className="shopping-cart">
<div className="products">
<h2>Products</h2>
{products.map(product => (
<div key={product.id} className="product">
<h3>{product.name}</h3>
<p>{product.price}</p>
<p>Stock: {product.stock}</p>
<button onClick={() => addToCart(product)}>
Add to Cart
</button>
</div>
))}
</div>
<div className="cart">
<h2>Shopping Cart</h2>
{cart.length === 0 ? (
<p>Your cart is empty</p>
) : (
<>
{cart.map(item => (
<div key={item.id} className="cart-item">
<span>{item.name}</span>
<span>{item.price}</span>
<input
type="number"
value={item.quantity}
onChange={(e) => updateQuantity(item.id, parseInt(e.target.value))}
min="1"
/>
<button onClick={() => removeFromCart(item.id)}>
Remove
</button>
</div>
))}
<div className="cart-total">
<strong>Total: {getTotalPrice()}</strong>
</div>
<button className="checkout-btn">Checkout</button>
</>
)}
</div>
</div>
);
}
// Challenge: Add stock validation
// Challenge: Add a wishlist feature
// Challenge: Add discount codes
Test your understanding of this topic:
Learn to use React Developer Tools for debugging and understanding React applications
Content by: Hiren Bhut
MERN Stack Developer
React Developer Tools is a browser extension that helps you inspect React components, view their props and state, and understand the component hierarchy. It's an essential tool for React development.
// After installing the extension, you'll see a new tab in your browser's developer tools
// 1. Components Tab
// - View component hierarchy
// - Inspect component props and state
// - See component names and file locations
// - Highlight components on the page
// 2. Profiler Tab
// - Record performance profiles
// - Analyze component render times
// - Identify performance bottlenecks
// - Optimize component rendering
// Example component to inspect
function UserProfile({ user, onUpdate }) {
const [isEditing, setIsEditing] = useState(false);
const [formData, setFormData] = useState(user);
const handleSubmit = (e) => {
e.preventDefault();
onUpdate(formData);
setIsEditing(false);
};
return (
<div className="user-profile">
{isEditing ? (
<form onSubmit={handleSubmit}>
<input
value={formData.name}
onChange={(e) => setFormData({
...formData,
name: e.target.value
})}
/>
<input
value={formData.email}
onChange={(e) => setFormData({
...formData,
email: e.target.value
})}
/>
<button type="submit">Save</button>
<button type="button" onClick={() => setIsEditing(false)}>
Cancel
</button>
</form>
) : (
<div>
<h2>{user.name}</h2>
<p>{user.email}</p>
<button onClick={() => setIsEditing(true)}>Edit</button>
</div>
)}
</div>
);
}
// In React DevTools, you can:
// - See the component tree
// - Inspect props and state values
// - Modify state in real-time
// - See component render times
// - Identify unnecessary re-renders
// Common debugging scenarios
// 1. Props not updating
function ParentComponent() {
const [user, setUser] = useState({ name: 'John', email: 'john@example.com' });
// Check in DevTools if props are being passed correctly
return <UserProfile user={user} onUpdate={setUser} />;
}
// 2. State not updating
function Counter() {
const [count, setCount] = useState(0);
// Use DevTools to see if state is actually changing
const increment = () => {
setCount(prev => prev + 1);
console.log('Count should be:', count + 1);
};
return (
<div>
<p>Count: {count}</p>
<button onClick={increment}>Increment</button>
</div>
);
}
// 3. Component not re-rendering
function ExpensiveComponent({ data }) {
// Use Profiler to see if component is re-rendering unnecessarily
console.log('ExpensiveComponent rendered');
return (
<div>
{data.map(item => (
<div key={item.id}>{item.name}</div>
))}
</div>
);
}
// 4. Performance optimization
function OptimizedComponent({ items }) {
// Use Profiler to measure render performance
const memoizedItems = useMemo(() => {
return items.filter(item => item.active);
}, [items]);
return (
<div>
{memoizedItems.map(item => (
<div key={item.id}>{item.name}</div>
))}
</div>
);
}
// Exercise: Debug a React Application
// Create a buggy component and use DevTools to fix it
// src/components/BuggyCounter.js
import React, { useState, useEffect } from 'react';
function BuggyCounter() {
const [count, setCount] = useState(0);
const [isRunning, setIsRunning] = useState(false);
// Bug: useEffect dependency array is missing
useEffect(() => {
let interval;
if (isRunning) {
interval = setInterval(() => {
setCount(prev => prev + 1);
}, 1000);
}
return () => clearInterval(interval);
}); // Missing dependency array!
return (
<div className="buggy-counter">
<h2>Count: {count}</h2>
<button onClick={() => setIsRunning(!isRunning)}>
{isRunning ? 'Stop' : 'Start'}
</button>
<button onClick={() => setCount(0)}>Reset</button>
</div>
);
}
// src/components/BuggyUserList.js
function BuggyUserList() {
const [users, setUsers] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
// Simulate API call
setTimeout(() => {
setUsers([
{ id: 1, name: 'John', email: 'john@example.com' },
{ id: 2, name: 'Jane', email: 'jane@example.com' },
{ id: 3, name: 'Bob', email: 'bob@example.com' }
]);
setLoading(false);
}, 2000);
}, []);
const deleteUser = (id) => {
// Bug: Not updating state correctly
users.filter(user => user.id !== id);
// Should be: setUsers(users.filter(user => user.id !== id));
};
if (loading) {
return <div>Loading...</div>;
}
return (
<div className="user-list">
<h2>Users</h2>
{users.map(user => (
<div key={user.id} className="user-item">
<span>{user.name}</span>
<span>{user.email}</span>
<button onClick={() => deleteUser(user.id)}>Delete</button>
</div>
))}
</div>
);
}
// Tasks:
// 1. Install React Developer Tools
// 2. Open the application in browser
// 3. Open DevTools and go to React tab
// 4. Identify the bugs using component inspection
// 5. Fix the bugs and verify in DevTools
// 6. Use Profiler to check performance
// Expected bugs to find:
// - useEffect missing dependency array
// - State not updating correctly
// - Unnecessary re-renders
// - Missing key props
Test your understanding of this topic:
Continue your learning journey and master the next set of concepts.
Continue to Module 2