Table of Contents
What are Props?
Props (short for "properties") are a way to pass data from parent components to child components in React. They make components reusable and dynamic by allowing them to receive different data and behave accordingly.
Understanding Props
Think of props like function parameters - they allow you to customize how a component behaves:
// Parent component passing props
function App() {
return (
<div>
<Greeting name="Alice" age={25} />
<Greeting name="Bob" age={30} />
</div>
);
}
// Child component receiving props
function Greeting(props) {
return (
<div>
<h2>Hello, {props.name}!</h2>
<p>You are {props.age} years old.</p>
</div>
);
}
Destructuring Props
You can destructure props to make your code cleaner:
// Method 1: Destructuring in function parameter
function Greeting({ name, age }) {
return (
<div>
<h2>Hello, {name}!</h2>
<p>You are {age} years old.</p>
</div>
);
}
// Method 2: Destructuring inside function
function Greeting(props) {
const { name, age } = props;
return (
<div>
<h2>Hello, {name}!</h2>
<p>You are {age} years old.</p>
</div>
);
}
Types of Props
Props can be any JavaScript data type:
function UserProfile({
name, // string
age, // number
isActive, // boolean
hobbies, // array
address, // object
onButtonClick // function
}) {
return (
<div className="user-profile">
<h2>{name}</h2>
<p>Age: {age}</p>
<p>Status: {isActive ? "Active" : "Inactive"}</p>
<div>
<h3>Address:</h3>
<p>{address.street}, {address.city}</p>
</div>
<div>
<h3>Hobbies:</h3>
<ul>
{hobbies.map((hobby, index) => (
<li key={index}>{hobby}</li>
))}
</ul>
</div>
<button onClick={onButtonClick}>
Contact User
</button>
</div>
);
}
// Using the component
function App() {
const user = {
name: "Sarah Johnson",
age: 28,
isActive: true,
hobbies: ["Reading", "Photography", "Hiking"],
address: {
street: "123 Main St",
city: "New York"
}
};
const handleContactClick = () => {
alert(`Contacting ${user.name}...`);
};
return (
<UserProfile
name={user.name}
age={user.age}
isActive={user.isActive}
hobbies={user.hobbies}
address={user.address}
onButtonClick={handleContactClick}
/>
);
}
Default Props
You can set default values for props:
function Button({ text, color, size, onClick }) {
return (
<button
className={`btn btn-${color} btn-${size}`}
onClick={onClick}
>
{text}
</button>
);
}
// Method 1: Default parameters
function Button({
text = "Click me",
color = "primary",
size = "medium",
onClick = () => {}
}) {
return (
<button
className={`btn btn-${color} btn-${size}`}
onClick={onClick}
>
{text}
</button>
);
}
// Method 2: defaultProps (legacy)
Button.defaultProps = {
text: "Click me",
color: "primary",
size: "medium",
onClick: () => {}
};
Props Validation with PropTypes
You can validate props to catch errors early:
import PropTypes from 'prop-types';
function UserCard({ name, age, email, isAdmin }) {
return (
<div className="user-card">
<h3>{name}</h3>
<p>Age: {age}</p>
<p>Email: {email}</p>
{isAdmin && <span className="admin-badge">Admin</span>}
</div>
);
}
UserCard.propTypes = {
name: PropTypes.string.isRequired,
age: PropTypes.number.isRequired,
email: PropTypes.string.isRequired,
isAdmin: PropTypes.bool
};
UserCard.defaultProps = {
isAdmin: false
};
Children Prop
The special `children` prop allows you to pass content between component tags:
function Card({ title, children }) {
return (
<div className="card">
<div className="card-header">
<h3>{title}</h3>
</div>
<div className="card-body">
{children}
</div>
</div>
);
}
// Using the Card component
function App() {
return (
<div>
<Card title="User Information">
<p>This content is passed as children</p>
<button>Edit Profile</button>
</Card>
<Card title="Statistics">
<ul>
<li>Total Users: 1,234</li>
<li>Active Sessions: 89</li>
</ul>
</Card>
</div>
);
}
Conditional Props
You can conditionally pass props:
function ProductCard({ product, showDiscount }) {
return (
<div className="product-card">
<h3>{product.name}</h3>
<p>${product.price}</p>
{showDiscount && product.discount && (
<div className="discount">
{product.discount}% OFF!
</div>
)}
<button>Add to Cart</button>
</div>
);
}
function App() {
const products = [
{ id: 1, name: "Laptop", price: 999, discount: 10 },
{ id: 2, name: "Phone", price: 699, discount: null }
];
return (
<div>
{products.map(product => (
<ProductCard
key={product.id}
product={product}
showDiscount={true}
/>
))}
</div>
);
}
Practical Exercise: Building a Blog Post Component
function BlogPost({
title,
author,
date,
content,
tags,
readTime,
onLike,
onShare
}) {
return (
<article className="blog-post">
<header>
<h1>{title}</h1>
<div className="post-meta">
<span>By {author}</span>
<span>{date}</span>
<span>{readTime} min read</span>
</div>
</header>
<div className="post-content">
{content}
</div>
<div className="post-tags">
{tags.map((tag, index) => (
<span key={index} className="tag">
#{tag}
</span>
))}
</div>
<footer className="post-actions">
<button onClick={onLike}>❤️ Like</button>
<button onClick={onShare}>📤 Share</button>
</footer>
</article>
);
}
// Using the BlogPost component
function App() {
const post = {
title: "Getting Started with React Props",
author: "Jane Developer",
date: "March 15, 2024",
content: "Props are one of the most important concepts in React...",
tags: ["React", "JavaScript", "Frontend"],
readTime: 5
};
const handleLike = () => {
console.log("Post liked!");
};
const handleShare = () => {
console.log("Post shared!");
};
return (
<div className="app">
<BlogPost
title={post.title}
author={post.author}
date={post.date}
content={post.content}
tags={post.tags}
readTime={post.readTime}
onLike={handleLike}
onShare={handleShare}
/>
</div>
);
}
Best Practices for Props
- Keep props simple: Pass only the data that the component needs
- Use descriptive names: Make prop names clear and meaningful
- Validate props: Use PropTypes or TypeScript for type checking
- Avoid prop drilling: Don't pass props through many levels unnecessarily
- Use default props: Provide sensible defaults for optional props
- Destructure props: Makes code more readable and easier to maintain
Common Mistakes to Avoid
- Mutating props: Props are read-only, never modify them directly
- Missing keys: Always provide keys when rendering lists
- Passing too many props: Consider using objects or context for complex data
- Not using PropTypes: Validation helps catch bugs early
Summary
Props are essential for creating reusable and dynamic React components. You've learned how to pass different types of data, use default props, validate props, and work with the special children prop. In the next lesson, we'll explore state management and how components can manage their own internal data.