Props are one of the most important concepts in React because they allow components to share data with each other. In most React applications, data flows from a parent component to a child component through props.
For example, a parent component might have a user’s name, course title, price, or progress percentage. Instead of hardcoding those values inside a child component, the parent can pass them as props.
Understanding how to pass props is essential for building reusable and dynamic React components.
What Does Passing Props Mean?
Passing props means sending data from one React component to another, usually from a parent component to a child component.
Think of props as information that a parent gives to its child.
function App() {
return <User name="Karimulla" />;
}
Here:
Appis the parent component.Useris the child component.nameis a prop."Karimulla"is the value passed through that prop.
The child can then read the prop.
function User(props) {
return <h2>Hello, {props.name}</h2>;
}
The browser displays:
Hello, Karimulla
The basic flow is:
Parent Component
↓
Props
↓
Child Component
↓
Render UI
Why Do We Pass Props?
Without props, reusable components would often need to contain hardcoded data.
For example:
function User() {
return <h2>Welcome, Karimulla</h2>;
}
This component can only display one specific name.
If you want to display different users, you would need different components or additional hardcoded values.
Props solve this problem.
function User({ name }) {
return <h2>Welcome, {name}</h2>;
}
Now the same component can be reused:
<User name="Karimulla" />
<User name="Rahul" />
<User name="John" />
The component remains the same, while the data changes.
Passing a String Prop
The simplest way to pass a prop is to provide a string value.
function App() {
return <Welcome name="Karimulla" />;
}
The Welcome component receives the name prop.
function Welcome(props) {
return <h2>Welcome, {props.name}</h2>;
}
Output:
Welcome, Karimulla
You can pass multiple string props as well.
function App() {
return (
<User
name="Karimulla"
city="Hyderabad"
role="Developer"
/>
);
}
The child can access each value:
function User(props) {
return (
<div>
<h2>{props.name}</h2>
<p>{props.city}</p>
<p>{props.role}</p>
</div>
);
}
Passing Multiple Props
A component can receive as many props as its design requires.
For example:
function App() {
return (
<Course
title="React"
level="Beginner"
duration="8 Weeks"
/>
);
}
The Course component receives all three props.
function Course(props) {
return (
<div>
<h2>{props.title}</h2>
<p>Level: {props.level}</p>
<p>Duration: {props.duration}</p>
</div>
);
}
The result could be:
React
Level: Beginner
Duration: 8 Weeks
Each prop is an independent piece of information.
Passing Numbers as Props
Numbers need curly braces when passed through JSX.
function App() {
return <Progress percentage={75} />;
}
Here, 75 is a JavaScript number.
The child can use it like this:
function Progress(props) {
return <p>Progress: {props.percentage}%</p>;
}
Output:
Progress: 75%
String vs Number
These two props are different:
<Progress percentage="75" />
and:
<Progress percentage={75} />
The first passes a string.
The second passes a number.
This difference becomes important when performing calculations.
function Progress({ percentage }) {
return <p>{percentage + 5}%</p>;
}
With:
<Progress percentage={75} />
the result is:
80%
With:
<Progress percentage="75" />
JavaScript string behavior can produce:
755
So use the appropriate data type when passing props.
Passing Boolean Props
Boolean values are also passed using curly braces.
function App() {
return <Course available={true} />;
}
The child can read the value:
function Course({ available }) {
return <p>{available ? "Available" : "Not Available"}</p>;
}
Output:
Available
Boolean Shorthand
When you want to pass true, React allows a shorter syntax.
Instead of:
<Course available={true} />
you can write:
<Course available />
Both represent:
available={true}
To pass false, use:
<Course available={false} />
Passing Variables as Props
Props don’t have to contain hardcoded values.
You can store data in variables and pass those variables.
function App() {
const courseName = "React";
const courseLevel = "Beginner";
return (
<Course
name={courseName}
level={courseLevel}
/>
);
}
The child receives the values:
function Course({ name, level }) {
return (
<div>
<h2>{name}</h2>
<p>{level}</p>
</div>
);
}
This approach becomes especially useful when data comes from APIs, state, databases, or user interactions.
Passing Objects as Props
You can pass an entire object to a component.
function App() {
const user = {
name: "Karimulla",
role: "Frontend Developer",
experience: 1
};
return <User user={user} />;
}
The child receives the object:
function User({ user }) {
return (
<div>
<h2>{user.name}</h2>
<p>{user.role}</p>
<p>{user.experience} year experience</p>
</div>
);
}
Objects are useful when several related values belong to the same entity.
For example:
const course = {
title: "React",
level: "Intermediate",
duration: "6 Weeks",
students: 1200
};
You can pass the complete object:
<Course course={course} />
Passing Arrays as Props
Arrays can also be passed to components.
function App() {
const topics = [
"JSX",
"Components",
"Props",
"State"
];
return <TopicList topics={topics} />;
}
The child can use the array:
function TopicList({ topics }) {
return (
<ul>
{topics.map((topic) => (
<li key={topic}>{topic}</li>
))}
</ul>
);
}
This produces:
- JSX
- Components
- Props
- State
Passing arrays is particularly useful for lists, menus, navigation items, products, courses, and other repeated UI.
Passing Functions as Props
Functions can also be passed as props.
This is an important React pattern because it allows a child component to trigger behavior defined by its parent.
function App() {
function handleClick() {
alert("Button clicked");
}
return <Button onClick={handleClick} />;
}
The child receives the function:
function Button({ onClick }) {
return (
<button onClick={onClick}>
Click Me
</button>
);
}
When the button is clicked, the child’s event handler calls the function provided by the parent.
The flow looks like:
Parent
│
│ passes function
↓
Child
│
│ calls function
↓
Parent's logic runs
This pattern is commonly used for child-to-parent communication.
Passing JSX as Props
Props can even contain JSX.
For example:
function App() {
return (
<Card
title="React"
icon={<span>⚛️</span>}
/>
);
}
The child can render the JSX:
function Card({ title, icon }) {
return (
<div>
{icon}
<h2>{title}</h2>
</div>
);
}
This allows a component to accept UI content from its parent without hardcoding that content.
The children prop is another common and especially useful way of passing JSX content.
Passing Props to Multiple Component Instances
The same component can be rendered multiple times with different props.
function App() {
return (
<Course
title="React"
level="Beginner"
/>
);
}
You can render it again:
function App() {
return (
<>
<Course title="React" level="Beginner" />
<Course title="JavaScript" level="Intermediate" />
<Course title="Python" level="Advanced" />
</>
);
}
The component is reused three times.
Each instance receives its own prop values.
This is one of the main reasons props are so important for reusable components.
Passing Props Through Component Levels
Sometimes data needs to travel through more than one component.
For example:
App
↓
Dashboard
↓
CourseCard
The App component can pass data to Dashboard:
<Dashboard course={course} />
Then Dashboard can pass it to CourseCard:
<CourseCard course={course} />
Finally, CourseCard can use it:
function CourseCard({ course }) {
return <h2>{course.title}</h2>;
}
This is called prop drilling when props are passed through components that don’t themselves need the data, simply to reach a deeper component.
Prop drilling is not automatically bad. For a small component tree, it can be perfectly reasonable.
For larger applications, React Context or state-management solutions can sometimes reduce unnecessary prop passing.
Passing Props with Destructuring
You can access props using the props object:
function Course(props) {
return <h2>{props.title}</h2>;
}
Or destructure them directly:
function Course({ title }) {
return <h2>{title}</h2>;
}
With multiple props:
function Course({ title, level, duration }) {
return (
<div>
<h2>{title}</h2>
<p>{level}</p>
<p>{duration}</p>
</div>
);
}
Both approaches work.
Destructuring is often preferred when the component uses several props because it makes the component’s expected data easier to see.
Passing Props to Control Styling
Props can also control how a component looks.
For example:
function App() {
return (
<Button variant="primary">
Start Learning
</Button>
);
}
The component can use the prop:
function Button({ variant, children }) {
return (
<button className={`button ${variant}`}>
{children}
</button>
);
}
Now the same component could support:
<Button variant="primary">Start Learning</Button>
<Button variant="secondary">View Course</Button>
<Button variant="danger">Delete</Button>
Instead of creating separate components such as:
PrimaryButton
SecondaryButton
DangerButton
you can create one reusable Button component with a controlled API.
Passing Props to Control Content
Props can determine what a component displays.
function CourseCard({ title, description }) {
return (
<article>
<h2>{title}</h2>
<p>{description}</p>
</article>
);
}
Different data produces different content:
<CourseCard
title="Learn React"
description="Build modern user interfaces."
/>
<CourseCard
title="Learn JavaScript"
description="Understand the language behind modern web development."
/>
The component structure stays the same.
Only the data changes.
Practical Example: Course Cards
Imagine Web4Learners has a course page.
Instead of creating separate components for every course, create one reusable component:
function CourseCard({ title, level, lessons, progress }) {
return (
<article className="course-card">
<h2>{title}</h2>
<p>Level: {level}</p>
<p>Lessons: {lessons}</p>
<p>Progress: {progress}%</p>
</article>
);
}
The parent can provide different information:
function App() {
return (
<main>
<CourseCard
title="React"
level="Beginner"
lessons={40}
progress={75}
/>
<CourseCard
title="JavaScript"
level="Intermediate"
lessons={60}
progress={50}
/>
<CourseCard
title="CSS"
level="Beginner"
lessons={35}
progress={90}
/>
</main>
);
}
The result is three different cards created from the same component.
This demonstrates the central idea of props:
The component defines how the UI works, while props provide the data that makes each instance different.
Props Flow From Parent to Child
React generally follows a one-way data flow.
Parent
│
├── name
├── level
└── progress
↓
Child
For example:
<CourseCard
name="React"
level="Beginner"
progress={75}
/>
The child receives those values.
function CourseCard({ name, level, progress }) {
// use props here
}
The child should not directly modify its props.
If the value needs to change, the parent generally changes the value it passes, often by updating its own state.
Props Are Read-Only
A component should treat its props as read-only.
For example, avoid doing this:
function User(props) {
props.name = "John";
return <h2>{props.name}</h2>;
}
Instead, if the data needs to change, the appropriate owner of that data should update it and pass the new value down.
For example:
function App() {
const [name, setName] = useState("Karimulla");
return <User name={name} />;
}
When the parent changes name, React can render the child with the new prop value.
The important distinction is:
A child cannot mutate the prop directly, but a prop value can change when the parent renders the child with a different value.
Common Mistakes When Passing Props
Forgetting Curly Braces for JavaScript Values
Incorrect:
<Course progress="75" />
if you intended a number.
Correct:
<Course progress={75} />
Calling a Function Instead of Passing It
Suppose you have:
function handleClick() {
console.log("Clicked");
}
Usually, pass the function:
<Button onClick={handleClick} />
rather than:
<Button onClick={handleClick()} />
The second version calls the function immediately during rendering instead of passing the function for the event to invoke later.
Using the Wrong Prop Name
If the parent passes:
<Course courseTitle="React" />
but the child expects:
function Course({ title }) {
return <h2>{title}</h2>;
}
title will be undefined.
The prop names must match:
function Course({ courseTitle }) {
return <h2>{courseTitle}</h2>;
}
Mutating Props
Avoid changing props directly.
props.progress = 100;
Props should be treated as read-only.
Passing Too Much Unrelated Data
Don’t pass every piece of parent data into every child.
Instead of:
<User
name={name}
age={age}
city={city}
theme={theme}
courses={courses}
settings={settings}
/>
when the component only needs name and city, pass what it actually needs:
<User
name={name}
city={city}
/>
A focused prop API makes components easier to understand and reuse.
Best Practices for Passing Props
- Use descriptive prop names.
- Pass only the data a component actually needs.
- Use the correct JavaScript data type.
- Use curly braces for JavaScript expressions.
- Treat props as read-only.
- Use functions as props for event communication.
- Use objects when several values belong together.
- Use arrays for collections of related data.
- Use destructuring when it improves readability.
- Keep reusable components focused.
- Avoid unnecessarily passing props through many component levels.
- Choose component boundaries based on responsibility rather than simply splitting every element.
A Simple Mental Model
When you see:
<Course
title="React"
level="Beginner"
progress={75}
/>
read it as:
Create a Course component
and give it:
title → "React"
level → "Beginner"
progress → 75
Inside the component:
function Course({ title, level, progress }) {
// use the received values
}
Think of props as inputs to a component.
Props
↓
┌──────────────┐
│ Component │
│ │
│ UI Logic │
└──────────────┘
↓
Rendered UI
Passing Props Cheat Sheet
| Requirement | Example |
|---|---|
| String | name="Karimulla" |
| Number | progress={75} |
| Boolean | available={true} |
| Boolean shorthand | available |
| Variable | name={userName} |
| Object | user={user} |
| Array | topics={topics} |
| Function | onClick={handleClick} |
| JSX | icon={<Icon />} |
| Multiple props | <Course title="React" level="Beginner" /> |
| Read prop | props.title |
| Destructure | function Course({ title }) |
Practice Exercise
Create a reusable ProfileCard component.
The parent should pass:
namerolelocationexperienceisAvailable
Start with:
function App() {
return (
<ProfileCard
name="Karimulla"
role="Frontend Developer"
location="Hyderabad"
experience={1}
isAvailable={true}
/>
);
}
Then create the ProfileCard component and display all five values.
After that, try creating two more profile cards using different prop values.
Image Placement
Place an image immediately after the section explaining “What Does Passing Props Mean?”
The image should visually show a parent React component passing several values into a child component. Use a modern 16:9 developer-style infographic with a clean React aesthetic. Show App on the left, arrows labeled props in the middle, and Course on the right with examples such as title, level, and progress. Keep the text minimal and make the data flow visually obvious.
Caption: Passing data from a parent component to a child component using props.
Alt text: React parent component passing props to a child component.
Key Takeaways
- Props allow components to receive data from other components.
- Props are most commonly passed from a parent to a child.
- Props make components reusable and dynamic.
- Props can contain strings, numbers, booleans, objects, arrays, functions, and JSX.
- JavaScript values such as numbers and variables are passed using curly braces.
- Functions can be passed as props to allow child components to trigger parent logic.
- The receiving component should treat props as read-only.
- The same component can be reused with different prop values.
- Good prop design makes components easier to understand and maintain.
- Props are one of the foundations of React’s one-way data flow.