Careeroza
Typing Props and Children
Props Type
Describe props with a type or interface and annotate the destructured parameter. Avoid React.FC in new code; a plain function with typed props is simpler and is what the React and Next.js docs use. (React itself is covered in the React material.)
type ProductCardProps = {
name: string;
price: number;
imageUrl?: string;
badge?: "new" | "sale" | "bestseller";
onAddToCart: (qty: number) => void;
};
export function ProductCard({ name, price, imageUrl = "/placeholder.png", badge, onAddToCart }: ProductCardProps) {
return (
<div className="card">
{badge && <span className={`badge badge-${badge}`}>{badge}</span>}
<img src={imageUrl} alt={name} />
<h3>{name}</h3>
<p>Rs. {price.toLocaleString("en-IN")}</p>
<button onClick={() => onAddToCart(1)}>Add to cart</button>
</div>
);
}
// <ProductCard name="Kettle" price={1299} badge="hot" /> -> error: "hot" not allowed, onAddToCart missingchildren and Other React Types
import type { ReactNode, ComponentProps, CSSProperties } from "react";
type CardProps = { title: string; children: ReactNode; style?: CSSProperties };
export function Card({ title, children, style }: CardProps) {
return <section style={style}><h2>{title}</h2>{children}</section>;
}
// Extend native element props: all <button> props + our own
type ButtonProps = ComponentProps<"button"> & { variant?: "primary" | "ghost"; loading?: boolean };
export function Button({ variant = "primary", loading = false, children, ...rest }: ButtonProps) {
return (
<button className={`btn btn-${variant}`} disabled={loading || rest.disabled} {...rest}>
{loading ? "Please wait..." : children}
</button>
);
}| Type | Use for |
|---|---|
ReactNode | anything renderable: JSX, string, number, null, arrays |
ReactElement | exactly one JSX element |
ComponentProps<"input"> | all props of a native element (or of another component) |
PropsWithChildren<P> | adds children?: ReactNode to P |