04. Props — Passing Data to Components
Level: Beginner
- Props: React component parameters
- Passing data from parent to child
- Prop types and defaults
- Destructuring props
- When NOT to use prop drilling
- Common prop patterns in SMS components
The Problem
In a School Management System, data flows from API to component to sub-component. Props let you pass data down the tree. Without understanding props, you'll either hardcode data (breaks reusability) or pass props 5 levels deep (prop drilling disaster).
Props are how React components talk to each other. Think of them as function parameters.
What Are Props?
Props allow you to pass data from parent to child component.
// Parent component
function StudentList() {
const students = [
{ id: 1, name: "Ravi Kumar", marks: 95 },
{ id: 2, name: "Priya Sharma", marks: 88 }
];
return (
<div>
<StudentCard student={students[0]} />
<StudentCard student={students[1]} />
</div>
);
}
// Child component — receives props
function StudentCard({ student }) {
return (
<div className="card">
<h3>{student.name}</h3>
<p>Marks: {student.marks}</p>
</div>
);
}
Props flow one direction: parent → child only. Child cannot directly modify parent's props.
Passing Different Types of Props
String Props
<StudentCard name="Ravi Kumar" className="10" />
function StudentCard({ name, className }) {
return <h3>{name} - Class {className}</h3>;
}
Number Props
<ExamCard maxMarks={100} passingMarks={40} />
function ExamCard({ maxMarks, passingMarks }) {
return <p>{passingMarks} out of {maxMarks}</p>;
}
Boolean Props
<StudentCard student={student} isActive={true} />
// Can also write isActive (shorthand for isActive={true})
<StudentCard student={student} isActive />
function StudentCard({ student, isActive }) {
return (
<div>
<h3>{student.name}</h3>
{isActive ? <span>Active</span> : <span>Inactive</span>}
</div>
);
}
Object Props
const student = {
id: 1,
name: "Ravi Kumar",
marks: 95,
className: "10"
};
<StudentCard student={student} />
function StudentCard({ student }) {
return (
<div>
<h3>{student.name}</h3>
<p>Marks: {student.marks}</p>
</div>
);
}
Array Props
const marks = [95, 88, 92];
<StudentMarks marks={marks} />
function StudentMarks({ marks }) {
return (
<ul>
{marks.map((mark, index) => (
<li key={index}>Exam {index + 1}: {mark}</li>
))}
</ul>
);
}
Function Props
// Pass a function as prop
<StudentCard
student={student}
onDelete={() => deleteStudent(student.id)}
/>
function StudentCard({ student, onDelete }) {
return (
<div>
<h3>{student.name}</h3>
<button onClick={onDelete}>Delete</button>
</div>
);
}
Common Prop Patterns
Pattern 1: Event Handlers
Prefix function props with on:
// Parent
function StudentList() {
const handleDelete = (studentId) => {
console.log(`Delete student ${studentId}`);
};
return (
<StudentCard
student={student}
onDelete={handleDelete}
onEdit={handleEdit}
onView={handleView}
/>
);
}
// Child
function StudentCard({ student, onDelete, onEdit, onView }) {
return (
<div>
<h3 onClick={() => onView(student.id)}>{student.name}</h3>
<button onClick={() => onEdit(student.id)}>Edit</button>
<button onClick={() => onDelete(student.id)}>Delete</button>
</div>
);
}
Pattern 2: Spread Operator for Props
If you have many props, you can spread them:
// Without spread
<StudentCard
name={student.name}
className={student.className}
rollNumber={student.rollNumber}
status={student.status}
/>
// With spread
<StudentCard {...student} />
// Both pass same data to StudentCard
function StudentCard({ name, className, rollNumber, status }) {
return (
<div>
<h3>{name}</h3>
<p>{className} - {rollNumber}</p>
</div>
);
}
Pattern 3: Conditional Props
function StudentCard({ student, showMarks = false }) {
return (
<div>
<h3>{student.name}</h3>
{showMarks && <p>Marks: {student.marks}</p>}
</div>
);
}
<StudentCard student={ravi} />
<StudentCard student={priya} showMarks={true} />
Pattern 4: Children Props
Use children for content passed inside a component:
// Parent passes content as children
<StudentCard student={student}>
<p>Custom content here</p>
<button>Action</button>
</StudentCard>
// Child receives as 'children' prop
function StudentCard({ student, children }) {
return (
<div className="card">
<h3>{student.name}</h3>
{children}
</div>
);
}
// Renders as:
// <div class="card">
// <h3>Ravi Kumar</h3>
// <p>Custom content here</p>
// <button>Action</button>
// </div>
More advanced pattern:
// Reusable layout component
function CardLayout({ title, children }) {
return (
<div className="card">
<div className="card-header">{title}</div>
<div className="card-body">{children}</div>
</div>
);
}
// Use it for different things
<CardLayout title="Student Info">
<p>Name: Ravi Kumar</p>
<p>Class: 10</p>
</CardLayout>
<CardLayout title="Exam Results">
<table>
{/* marks table */}
</table>
</CardLayout>
Props Validation — Documenting What a Component Needs
There's no enforcement in plain JavaScript, but you can document:
// Document what props a component needs
function StudentCard({ student, onDelete }) {
// student: object with { id, name, className, marks }
// onDelete: function that takes studentId
return (
<div>
<h3>{student.name}</h3>
<button onClick={() => onDelete(student.id)}>Delete</button>
</div>
);
}
We'll see better validation with TypeScript later.
Building a Real Example: Student Management
// Main component
function StudentManagement() {
const students = [
{ id: 1, name: "Ravi Kumar", className: "10", marks: 95 },
{ id: 2, name: "Priya Sharma", className: "10", marks: 88 },
{ id: 3, name: "Arjun Reddy", className: "11", marks: 92 }
];
const handleDelete = (id) => {
console.log(`Deleting student ${id}`);
};
const handleEdit = (id) => {
console.log(`Editing student ${id}`);
};
return (
<div className="management">
<h1>Students</h1>
<div className="student-list">
{students.map(student => (
<StudentCard
key={student.id}
student={student}
onDelete={handleDelete}
onEdit={handleEdit}
/>
))}
</div>
</div>
);
}
// Reusable component
function StudentCard({ student, onDelete, onEdit }) {
return (
<div className="student-card">
<div className="info">
<h3>{student.name}</h3>
<p>Class: {student.className}</p>
<p>Marks: {student.marks}</p>
</div>
<div className="actions">
<button onClick={() => onEdit(student.id)}>Edit</button>
<button onClick={() => onDelete(student.id)}>Delete</button>
</div>
</div>
);
}
Prop Drilling Problem (Preview)
When you have deeply nested components, passing props gets tedious:
function App() {
const user = { name: "Admin", role: "Principal" };
return <SchoolDashboard user={user} />;
}
function SchoolDashboard({ user }) {
return <StudentSection user={user} />;
}
function StudentSection({ user }) {
return <StudentList user={user} />;
}
function StudentList({ user }) {
return <StudentCard user={user} />;
}
function StudentCard({ user }) {
return <div>Admin: {user.name}</div>;
}
Passing user through 5 levels just to use it at the bottom is annoying. We'll solve this later with Context API.
Key Points
- Props flow parent → child only
- Props are read-only
- Use meaningful names (
onDelete, notfn) - Default props with
= value - Spread operator for multiple props
childrenfor flexible content- Next: State — how to modify data
- Trying to modify props — Props are read-only. Use state to change data
- Passing props too deeply — If you're passing through 5+ levels, use Context
- Naming function props without
on— UseonClick,onDelete, notclick,delete - Forgetting key prop in lists — We'll cover this next article
- Props = data flowing in from parent (read-only)
- State = data the component manages itself (can change)
More on state next article.
Use ChatGPT, Claude, or Copilot to go deeper on Props Mastery. Try these prompts:
"Can a child component modify the props it receives? Why or why not?""What's the purpose of naming function props with 'on' prefix?""When would you use the children prop?""Quiz me on React props"
💡 Tip: After reading this article, paste your own code into AI and ask "What could go wrong here and why?" — fastest way to find edge cases and deepen understanding.
Quick Definitions
- Props — Passing Data to Components - The main React concept explained in this lesson.
- Component - A reusable function that returns UI.
- Props/state/effects - Core React ideas used to pass data, remember data, and run side effects.
- Real project usage - How this appears in forms, dashboards, routes, and API-connected pages.
Common Mistakes
- Copying React code without understanding data flow
- Mutating arrays or objects directly instead of creating new values
- Forgetting keys, dependencies, loading states, or error states where needed
- Putting too much logic in one component
- Not testing the screen with realistic School Management System data
Practice Task
Create a small React example using Props — Passing Data to Components. Keep it focused on one School Management System screen.
Suggested practice:
- Build a small component or page for students, attendance, marks, or fees.
- Pass realistic data into the component.
- Add one success state and one empty/error state where relevant.
- Explain the data flow in your own words.
- Rebuild the same example once without looking at the article.
Quick Revision
| Question | Answer |
|---|---|
| What is the main idea? | Understand and apply Props — Passing Data to Components in React. |
| Where is it used? | Student dashboards, forms, tables, routes, and API-connected screens. |
| What should beginners focus on? | Clear components, predictable data flow, and small examples. |
| What is the best debugging habit? | Check props, state, render output, and browser console step by step. |
Props — Passing Data to Components is a React concept used to build clear, reusable, and predictable user interfaces. I would explain the problem it solves, show a small component example, and mention a common mistake beginners should avoid.
It is used in screens like student lists, admission forms, attendance dashboards, marks reports, routing pages, and API-connected admin panels.