Chapter 4: Props
1. What are Props? (The most important concept)
Props = Properties They are read-only data that a parent component passes down to a child component.
Analogy: Imagine a toy factory that makes customizable teddy bears. The factory (parent component) decides:
- What color fur?
- What size eyes?
- What message on the t-shirt?
These choices are props. The teddy bear machine (child component) just receives them and builds the bear accordingly — it can’t change the instructions.
Important rules about props:
- Props are read-only inside the child component (you cannot do props.name = “new name”)
- Props flow one way: parent → child (never child → parent directly)
- Props can be any JavaScript value: string, number, boolean, object, array, function, even other components!
2. Passing Data with Props (Basic Example)
Let’s create a reusable UserCard component.
Create new file: src/components/UserCard.tsx
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
// UserCard.tsx interface UserCardProps { name: string; age: number; city: string; isStudent: boolean; } function UserCard(props: UserCardProps) { return ( <div style={{ border: '2px solid #646cff', borderRadius: '12px', padding: '20px', margin: '20px auto', maxWidth: '400px', backgroundColor: '#f8f9ff', boxShadow: '0 4px 12px rgba(0,0,0,0.1)' }}> <h2>Hello, {props.name}!</h2> <p>Age: {props.age} years</p> <p>Lives in: {props.city}</p> <p>{props.isStudent ? "🎓 Currently a student" : "💼 Working professional"}</p> </div> ); } export default UserCard; |
Now use it in App.tsx (multiple times with different data!):
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
// App.tsx import UserCard from './components/UserCard'; import Header from './components/Header'; // if you have it function App() { return ( <div style={{ padding: '20px', maxWidth: '900px', margin: '0 auto' }}> <Header /> {/* optional */} <h1 style={{ textAlign: 'center', color: '#646cff' }}> Welcome to Props Chapter! 🚀 </h1> {/* Different instances with different props */} <UserCard name="Webliance" age={25} city="Mumbai" isStudent={true} /> <UserCard name="Priya" age={28} city="Bangalore" isStudent={false} /> <UserCard name="Rahul" age={22} city="Delhi" isStudent={true} /> </div> ); } export default App; |
Boom! Same component → 3 completely different cards. That’s the power of props.
3. Props Destructuring (Cleaner & Modern Way)
Most React developers never use props.xxx — they destructure props.
Improved version of UserCard.tsx:
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
// UserCard.tsx (cleaner) interface UserCardProps { name: string; age: number; city: string; isStudent: boolean; } function UserCard({ name, age, city, isStudent }: UserCardProps) { return ( <div style={{ /* same styles */ }}> <h2>Hello, {name}!</h2> <p>Age: {age} years</p> <p>Lives in: {city}</p> <p>{isStudent ? "🎓 Currently a student" : "💼 Working professional"}</p> </div> ); } |
Even shorter (with default values directly in destructuring — we’ll talk about defaults soon):
|
0 1 2 3 4 5 6 7 8 |
function UserCard({ name, age = 20, city = "Unknown", isStudent = false }: UserCardProps) { // ... } |
4. Default Props & Prop Types (Type Safety + Defaults)
A. Default Props (What happens if parent forgets to pass a prop?)
Two modern ways in 2026:
Way 1: Default values in destructuring (most popular)
|
0 1 2 3 4 5 6 7 8 |
function UserCard({ name, age = 18, city = "Mumbai", isStudent = false }: UserCardProps) { // ... } |
Way 2: Using defaultProps (older way, still works)
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
function UserCard(props: UserCardProps) { // ... } UserCard.defaultProps = { age: 18, city: "Mumbai", isStudent: false }; |
B. Prop Types (Optional but very helpful for catching bugs)
Install prop-types (if you want classic runtime checking):
|
0 1 2 3 4 5 6 |
npm install prop-types |
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
import PropTypes from 'prop-types'; // ... UserCard.propTypes = { name: PropTypes.string.isRequired, age: PropTypes.number, city: PropTypes.string, isStudent: PropTypes.bool }; |
But honestly in 2026 with TypeScript → you don’t need prop-types anymore because TypeScript already gives you compile-time safety + editor autocompletion.
5. Children Props (Super Powerful!)
Sometimes you want to pass JSX or content between opening and closing tags.
Example: Create a FancyBox component
src/components/FancyBox.tsx
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
interface FancyBoxProps { title: string; children: React.ReactNode; // ← this allows any JSX inside } function FancyBox({ title, children }: FancyBoxProps) { return ( <div style={{ border: '3px solid #ff6b6b', borderRadius: '16px', padding: '24px', margin: '20px 0', background: 'linear-gradient(135deg, #fff, #f0f4ff)', boxShadow: '0 8px 20px rgba(255,107,107,0.2)' }}> <h3 style={{ color: '#ff6b6b', marginTop: 0 }}>{title}</h3> <div>{children}</div> {/* ← children appear here! */} </div> ); } export default FancyBox; |
Use it like this in App.tsx:
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<FancyBox title="Important Announcement"> <p>This is some important content inside the fancy box.</p> <button style={{ padding: '10px 20px', background: '#ff6b6b', color: 'white', border: 'none', borderRadius: '8px' }}> Learn More </button> <p>You can put <strong>anything</strong> here — even other components!</p> </FancyBox> <FancyBox title="Your Progress"> <ul> <li>Chapter 1: Introduction ✅</li> <li>Chapter 2: JSX ✅</li> <li>Chapter 3: Components ✅</li> <li>Chapter 4: Props (current) 🚀</li> </ul> </FancyBox> |
Your Mini Exercise (Do this now!)
- Create a new component ProfileCard.tsx
- It should accept props:
- name (string, required)
- role (string, default: “React Learner”)
- bio (string)
- skills (array of strings)
- Use destructuring
- Show a nice card with name, role, bio, and a list of skills
- Use it twice in App.tsx with different data
- Bonus: Wrap one of them inside a FancyBox
Summary – Chapter 4 Key Takeaways
- Props = data passed from parent to child
- Always destructure props — cleaner code
- Use TypeScript interfaces for prop types (best in 2026)
- Default values in destructuring = easiest way
- children prop lets you pass content between tags
- Props are read-only — never mutate them inside child
