1. Introduction đ
Props (short for properties) are how data flows from parent to child components in React. They allow components to be configurable and reusable, forming the backbone of React's component communication model. This tutorial covers everything from passing basic values to advanced patterns like prop spreading and TS validation.
Information
2. What are Props? đ¤
Props are read-only inputs passed into a component, similar to arguments passed into a function. They let a parent component customize how a child component behaves and appears.
Code Snippet
function Greeting(props) {
return <h1>Hello, {props.name}! đ</h1>;
}
<Greeting name="Alice" />3. Why Props? đĄ
- Reusability: The same component renders differently based on the props it receives.
- Composition: Parent components configure and combine child components flexibly.
- Predictability: Since props are read-only, data flow remains clear and traceable.
- Separation of Concerns: Child components stay generic and reusable, unaware of where their data comes from.
4. Passing Props đ¤
Props are passed to a component the same way you'd set attributes on an HTML element â using a name={value} syntax within the JSX tag.
Code Snippet
<UserCard name="Alice" age={28} isVerified={true} />- String values can use quotes directly: name="Alice".
- Non-string values require curly braces: age={28}.
5. Receiving Props đĨ
A function component receives all its props bundled into a single object, typically named props, as its first argument.
Code Snippet
function UserCard(props) {
return (
<div>
<h2>{props.name}</h2>
<p>Age: {props.age}</p>
</div>
);
}6. Reading Props đ
Props are accessed like regular object properties. Most commonly, they're destructured directly in the function's parameter list for cleaner code.
Code Snippet
// Accessing via props object
function UserCard(props) {
return <h2>{props.name}</h2>;
}
// Destructured directly (preferred)
function UserCard({ name }) {
return <h2>{name}</h2>;
}Tip
7. Props vs State âī¸
| Aspect | Props | State |
|---|---|---|
| Ownership | Passed in from a parent | Owned by the component itself |
| Mutability | Read-only from the child's view | Can be updated via setter functions |
| Purpose | Configures a component externally | Tracks internal, changing data |
| Direction | Flows downward, parent â child | Local to the owning component |
8. Multiple Props đĸ
Code Snippet
function ProductCard({ name, price, inStock, imageUrl }) {
return (
<div className="product-card">
<img src={imageUrl} alt={name} />
<h3>{name}</h3>
<p>${price.toFixed(2)}</p>
<p>{inStock ? "In Stock â
" : "Out of Stock â"}</p>
</div>
);
}
<ProductCard name="Headphones" price={79.99} inStock={true} imageUrl="/headphones.jpg" />9. Default Props đ¯
In function components, default values are provided directly in the destructured parameter list, ensuring a fallback when a prop isn't passed.
Code Snippet
function Button({ label = "Click Me", variant = "primary" }) {
return <button className={`btn btn-${variant}`}>{label}</button>;
}
<Button /> {/* Uses both defaults */}
<Button label="Save" /> {/* Uses default variant */}
<Button label="Delete" variant="danger" />Note
10. Children Prop đļ
children is a special prop that represents whatever content is nested between a component's opening and closing tags.
Code Snippet
function Card({ children }) {
return <div className="card">{children}</div>;
}
<Card>
<h2>Title</h2>
<p>Some content inside the card.</p>
</Card>Tip
11. Passing JSX as Props đ§Š
Beyond children, any prop can accept JSX as its value, enabling flexible, named "slots" within a component.
Code Snippet
function PageLayout({ header, footer, children }) {
return (
<div>
<header>{header}</header>
<main>{children}</main>
<footer>{footer}</footer>
</div>
);
}
<PageLayout
header={<h1>My Site</h1>}
footer={<p>Š 2026</p>}
>
<p>Main page content</p>
</PageLayout>12. Passing Components as Props đ§Ŧ
Entire component references can be passed as props, letting a parent decide which component a child should render â a powerful pattern for flexible layouts and icons.
Code Snippet
function Alert({ Icon, message }) {
return (
<div className="alert">
<Icon />
<span>{message}</span>
</div>
);
}
<Alert Icon={WarningIcon} message="Low disk space" />Note
13. Passing Functions as Props đ
Functions are commonly passed as props to let child components communicate events back up to their parent â since data itself only flows downward.
Code Snippet
function SearchBar({ onSearch }) {
const [query, setQuery] = useState("");
return (
<input
value={query}
onChange={(e) => {
setQuery(e.target.value);
onSearch(e.target.value);
}}
/>
);
}
<SearchBar onSearch={(query) => console.log("Searching for:", query)} />14. Passing Objects as Props đĻ
Code Snippet
function UserProfile({ user }) {
return (
<div>
<h2>{user.name}</h2>
<p>{user.email}</p>
</div>
);
}
<UserProfile user={{ name: "Alice", email: "alice@example.com" }} />Tip
15. Passing Arrays as Props đ
Code Snippet
function TagList({ tags }) {
return (
<div>
{tags.map((tag) => <span key={tag} className="tag">{tag}</span>)}
</div>
);
}
<TagList tags={["react", "javascript", "webdev"]} />16. Passing Styles as Props đ¨
Code Snippet
function Box({ style, children }) {
return <div style={{ padding: "16px", ...style }}>{children}</div>;
}
<Box style={{ backgroundColor: "#f0f9ff", borderRadius: "8px" }}>
Content here
</Box>Tip
17. Passing Event Handlers as Props đąī¸
Code Snippet
function DeleteButton({ onDelete, itemId }) {
return <button onClick={() => onDelete(itemId)}>Delete</button>;
}
function TodoItem({ id, text, onDelete }) {
return (
<li>
{text}
<DeleteButton itemId={id} onDelete={onDelete} />
</li>
);
}Best Practice
18. Prop Drilling đŗī¸
Prop drilling occurs when a prop must be passed through several intermediate components that don't actually use it, just to reach a deeply nested child.
Code Snippet
function App() {
const [user, setUser] = useState({ name: "Alice" });
return <Layout user={user} />;
}
function Layout({ user }) {
return <Sidebar user={user} />; // Layout doesn't use 'user' itself
}
function Sidebar({ user }) {
return <UserBadge user={user} />; // neither does Sidebar
}
function UserBadge({ user }) {
return <p>{user.name}</p>; // finally used here
}Warning
19. Immutable Props đ
Props are read-only â a component must never modify the props it receives. If a value needs to change, it should be lifted into state in the owning component instead.
Code Snippet
function Bad({ count }) {
count = count + 1; // â Never mutate props directly
return <p>{count}</p>;
}
function Good({ count }) {
const displayCount = count + 1; // â
Derive a new value instead
return <p>{displayCount}</p>;
}Danger
20. Props Destructuring đ¤
Code Snippet
// Without destructuring
function UserCard(props) {
return <h2>{props.name} ({props.role})</h2>;
}
// With destructuring (preferred)
function UserCard({ name, role }) {
return <h2>{name} ({role})</h2>;
}Tip
21. Rest Props â
The rest operator (...rest) collects any remaining props not explicitly destructured, useful for forwarding extra attributes to an underlying element.
Code Snippet
function TextInput({ label, ...rest }) {
return (
<div>
<label>{label}</label>
<input {...rest} />
</div>
);
}
<TextInput label="Email" type="email" placeholder="you@example.com" required />Note
22. Spreading Props đ
The spread operator ({...props}) passes all properties of an object as individual props at once, useful for forwarding or reusing prop sets.
Code Snippet
const buttonProps = { label: "Submit", variant: "primary", disabled: false };
<Button {...buttonProps} />
// Equivalent to:
<Button label="Submit" variant="primary" disabled={false} />Caution
23. Conditional Props đ
Code Snippet
function SubmitButton({ isLoading }) {
return (
<Button
label={isLoading ? "Submitting..." : "Submit"}
disabled={isLoading}
/>
);
}24. Dynamic Props đ
Props can be computed dynamically based on other data, then spread or passed individually, allowing components to adapt based on runtime conditions.
Code Snippet
function DynamicField({ fieldConfig }) {
const inputProps = {
type: fieldConfig.type,
placeholder: fieldConfig.placeholder,
...(fieldConfig.type === "number" && { min: 0, max: 100 }),
};
return <input {...inputProps} />;
}25. Optional Props â
Not every prop needs to be required. Optional props typically have a default value or are conditionally checked before use.
Code Snippet
function Avatar({ src, size = 40, alt = "User avatar" }) {
return (
<img
src={src || "/default-avatar.png"}
width={size}
height={size}
alt={alt}
/>
);
}26. Props Validation â
PropTypes is a runtime validation library that can check prop types during development and warn about mismatches in the console.
Code Snippet
import PropTypes from 'prop-types';
function UserCard({ name, age }) {
return <h2>{name} ({age})</h2>;
}
UserCard.propTypes = {
name: PropTypes.string.isRequired,
age: PropTypes.number,
};Best Practice
27. TypeScript with Props đˇ
TS lets you define an explicit interface or type describing exactly what props a component accepts.
Code Snippet
interface ButtonProps {
label: string;
variant?: "primary" | "secondary" | "danger";
onClick: () => void;
disabled?: boolean;
}
function Button({ label, variant = "primary", onClick, disabled }: ButtonProps) {
return (
<button className={`btn btn-${variant}`} onClick={onClick} disabled={disabled}>
{label}
</button>
);
}Tip
28. Props Best Practices đ
- Keep prop names clear and descriptive, avoiding overly generic names like data or info.
- Destructure props directly in the function signature for readability.
- Provide sensible default values for optional props.
- Never mutate props â treat them as strictly read-only.
- Avoid passing too many individual props â group related data into an object when it makes sense.
- Use Context to avoid excessive prop drilling for deeply shared data.
29. Common Props Mistakes đĢ
- Mutating props directly instead of deriving new values.
- Forgetting to provide default values for optional props, leading to undefined errors.
- Excessive prop drilling through many layers of unrelated components.
- Overusing the spread operator, obscuring which props a component actually expects.
- Passing new inline object or array literals as props on every render, causing unnecessary re-renders in memoized children.
Danger
30. Frequently Asked Questions â
Question
Answer
Question
Answer
Question
Answer
31. Summary đ
Props enable React's component-based architecture by allowing data to flow predictably from parent to child. From simple string values to functions, objects, and even other components, mastering how to pass, destructure, and validate props is essential for building flexible, reusable UI.