Props
Props are a component’s inputs — like arguments to a function. They let one component be reused with different data, and let parents tell children what to show and what to do.
On this page · 5 min · Beginner
On this page
- Learning objectives
- Explanation
- Syntax
- Code example
- Step by step
- Real-world use
- Common mistakes
- Best practices
- Remember this
- Practice exercise
- Mini quiz
- Related topics
- My notes
- Reading time
- 5 min
- Difficulty
- Beginner
- Updated
- Oct 28, 2026
Related tutorials
Learning objectives#
- Pass and read props
- Destructure props with default values
- Pass functions as props (callbacks)
- Use the special children prop
Explanation#
Props are passed as attributes: <ProductCard name="Pen" price={20} />. Strings can use quotes; everything else goes in { }.
The component receives one object; destructure it: function ProductCard({ name, price = 0 }). Defaults apply when a prop is missing.
Props are read-only. A component must never change its props — data flows one way, from parent to child.
To let a child talk back, pass a function: <AddButton onAdd={handleAdd} />. The child calls onAdd(...) and the parent decides what happens.
children is whatever you put between the tags: <Card><p>Hi</p></Card>. It makes layout components (Card, Modal, Layout) easy.
Spread passes many props at once: <Input {...field} />. Use it carefully — explicit props are easier to read.
Syntax#
<Button label="Save" disabled={false} onClick={save} />
function Button({ label, disabled = false, onClick }) {
return <button disabled={disabled} onClick={onClick}>{label}</button>;
}
Code example: Data down, events up, children inside#
import { useState } from 'react';
function Card({ title, children }) {
return (
<section style={{ border: '1px solid #ddd', padding: 12, marginBottom: 8 }}>
<h3>{title}</h3>
{children}
</section>
);
}
function ProductRow({ name, price, currency = '₹', onAdd }) {
return (
<p>
{name} — {currency}{price}{' '}
<button onClick={() => onAdd(name)}>Add</button>
</p>
);
}
export default function Shop() {
const [cart, setCart] = useState([]);
function handleAdd(name) {
setCart(prev => [...prev, name]);
}
return (
<>
<Card title="Products">
<ProductRow name="Pen" price={20} onAdd={handleAdd} />
<ProductRow name="Notebook" price={60} onAdd={handleAdd} />
</Card>
<Card title={`Cart (${cart.length})`}>
<p>{cart.length ? cart.join(', ') : 'Empty'}</p>
</Card>
</>
);
}
Two cards: “Products” with Pen and Notebook rows, and “Cart (0)” showing “Empty”. Clicking Add on a row adds that product to the cart; the second card title and list update, e.g. “Cart (2)” — “Pen, Notebook”.
This example is illustrative. Copy or download it and run it in your own environment; the expected output is shown above.
Step-by-step explanation#
- Card receives title as a prop and renders whatever is nested inside it via children.
- ProductRow receives data (name, price) and a default currency.
- onAdd is a function prop: the row calls it, Shop decides what adding means.
- Shop owns the cart state; the rows never change it directly.
Real-world use case#
A design system exposes <Button variant="primary" size="sm" onClick={...}> and <Modal title="..." onClose={...}>{content}</Modal>. Every team uses the same components with different props.
Common mistakes#
props.price = 10 breaks one-way data flow and React’s assumptions. Copy into state or ask the parent via a callback.
onAdd={handleAdd("Pen")} runs on every render. Pass a function: onAdd={() => handleAdd("Pen")}.
Passing the same prop through five components that do not use it is a sign to use context or composition.
Best practices#
- Destructure props with defaults
- Name callback props onSomething
- Use children for layout components
- Keep props few and meaningful
Remember this#
Props in, JSX out. Props are read-only.
Data down via props; events up via callback props.
children = what goes between the tags.
Practice exercise#
Your task: Create an Alert component with a type prop ("success" or "error", default "success") and children. Success shows a green border, error a red one.
Need a hint?
Show solution
export default function Alert({ type = 'success', children = 'Saved!' }) {
const colour = type === 'error' ? 'red' : 'green';
return (
<div role="alert" style={{ border: `2px solid ${colour}`, padding: 8 }}>
{children}
</div>
);
}
// <Alert type="error">Payment failed</Alert>
Mini quiz#
How does a child component tell its parent that something happened?
Want more? Practise all React MCQs · React interview questions
My notes#
Saved in this browser.