React Props
Props (short for properties) are how you pass data from a parent component to a child component. Props flow in one direction: parent โ child. They are read-only โ a component must never modify its own props.
Passing Props
// Parent sends props like HTML attributes
function App() {
return (
<Product
name="React Handbook"
price={29.99}
inStock={true}
tags={["books", "programming"]}
onAddToCart={() => console.log("Added!")}
/>
);
}
// Child receives props as a single object โ destructure for clarity
function Product({ name, price, inStock, tags, onAddToCart }) {
return (
<div className="product">
<h2>{name}</h2>
<p className="price">${price.toFixed(2)}</p>
<p>{inStock ? "โ
In Stock" : "โ Out of Stock"}</p>
<ul>{tags.map(t => <li key={t}>{t}</li>)}</ul>
<button onClick={onAddToCart} disabled={!inStock}>
Add to Cart
</button>
</div>
);
}
Default Props
function Button({ label, variant = "primary", size = "md", disabled = false, onClick }) {
return (
<button
className={`btn btn-${variant} btn-${size}`}
disabled={disabled}
onClick={onClick}
>
{label}
</button>
);
}
// Without variant or size, defaults kick in
<Button label="Save" onClick={handleSave} />
// Renders with variant="primary" and size="md"
Prop Types (Runtime Validation)
import PropTypes from "prop-types"; // npm install prop-types
function UserCard({ name, age, email, onContact }) {
return (/* ... */);
}
UserCard.propTypes = {
name: PropTypes.string.isRequired,
age: PropTypes.number,
email: PropTypes.string.isRequired,
onContact: PropTypes.func,
};
UserCard.defaultProps = {
age: null,
onContact: () => {},
};
Spreading Props
// Pass all props of an object at once using spread
function TextInput(props) {
return <input className="text-input" {...props} />;
}
// Usage: all HTML input attributes work automatically
<TextInput
type="email"
placeholder="Enter email"
required
autoFocus
/>