Props are how components talk to each other. A parent component passes data down to a child through props, creating a one-way data flow that makes your app predictable and easy to debug.
Passing Props
Props are passed as attributes in JSX and received as a single object parameter in the component function:
function Button({ label, variant }: { label: string; variant: "primary" | "secondary" }) {
const styles =
variant === "primary"
? "bg-blue-600 text-white"
: "bg-gray-200 text-gray-800";
return <button className={`px-4 py-2 rounded ${styles}`}>{label}</button>;
}
// Usage
<Button label="Save" variant="primary" />
<Button label="Cancel" variant="secondary" />
Props are read-only. A component must never modify the props it receives.
Defining a Props Interface
For components with more than a couple of props, define a separate interface for clarity:
interface ProductCardProps {
name: string;
price: number;
imageUrl: string;
inStock: boolean;
}
function ProductCard({ name, price, imageUrl, inStock }: ProductCardProps) {
return (
<div className="border rounded-lg p-4">
<img src={imageUrl} alt={name} className="w-full h-48 object-cover" />
<h3 className="mt-2 font-semibold">{name}</h3>
<p className="text-lg">${price.toFixed(2)}</p>
{!inStock && <span className="text-red-500 text-sm">Out of stock</span>}
</div>
);
}The children Prop
The children prop lets a component wrap arbitrary content. Anything placed between a component's opening and closing tags becomes children:
function Card({ children, title }: { children: React.ReactNode; title: string }) {
return (
<div className="border rounded-lg shadow-sm">
<div className="border-b px-4 py-2 font-semibold">{title}</div>
<div className="p-4">{children}</div>
</div>
);
}
// Usage
<Card title="Settings">
<p>Manage your account preferences here.</p>
<button>Edit Profile</button>
</Card>Use React.ReactNode as the type for children — it covers strings, numbers, JSX elements, arrays, and fragments.
Default Props
Use JavaScript default parameter values to define fallback props:
interface AlertProps {
message: string;
type?: "info" | "warning" | "error";
dismissible?: boolean;
}
function Alert({ message, type = "info", dismissible = false }: AlertProps) {
const colors = {
info: "bg-blue-100 text-blue-800",
warning: "bg-yellow-100 text-yellow-800",
error: "bg-red-100 text-red-800",
};
return (
<div className={`p-3 rounded ${colors[type]} flex justify-between`}>
<span>{message}</span>
{dismissible && <button className="ml-4 font-bold">×</button>}
</div>
);
}
// Uses defaults: type="info", dismissible=false
<Alert message="Your changes have been saved." />
Spreading Props
When you need to forward many props to an underlying element, use the spread operator:
interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {
label: string;
}
function Input({ label, ...rest }: InputProps) {
return (
<div className="flex flex-col gap-1">
<label className="text-sm font-medium">{label}</label>
<input className="border rounded px-3 py-2" {...rest} />
</div>
);
}
// All standard input attributes are forwarded
<Input label="Email" type="email" placeholder="you@example.com" required />
This pattern is common for wrapper components that add styling or layout around a native element.
One-Way Data Flow
Data in React flows in one direction: parent to child. This is by design. If a child needs to communicate back to the parent, the parent passes a callback function as a prop:
function SearchBar({ onSearch }: { onSearch: (query: string) => void }) {
return (
<input
type="text"
placeholder="Search..."
onChange={(e)=> onSearch(e.target.value)}
/>
);
}
function App() {
function handleSearch(query: string) {
console.log("Searching for:", query);
}
return <SearchBar onSearch={handleSearch} />;
}The child doesn't know what happens with the data — it just calls the function it was given. This keeps components decoupled.
Summary
- Props are read-only data passed from parent to child.
- Use TypeScript interfaces to define prop shapes.
childrenis a special prop for wrapping content.- Use default parameter values for optional props.
- Spread props with
...restto forward attributes. - Data flows one way; use callback props for child-to-parent communication.