Destructuring Props
Overview
When a component receives data, React automatically bundles all the passed attributes into a single JavaScript object called props. If you pass 5 attributes, you constantly have to write props.title, props.price, props.image, etc., throughout your component. This makes your code unnecessarily wordy and harder to read.
To solve this, React developers universally use JavaScript Object Destructuring directly in the function signature. Destructuring allows you to unpack specific properties from the props object and assign them to local variables immediately as the function receives them.
Not only does this make your JSX much cleaner by removing the repetitive props. prefix, but it also clearly documents exactly which data a component expects right at the very top of the file, making it dramatically easier for other engineers to understand your code.
Syntax
// BAD (Old fashioned): Repetitive props. prefix
function ProductCard(props) {
return (
<div>
<h2>{props.name}</h2>
<p>{props.price}</p>
<img src={props.image} alt={props.name} />
</div>
);
}
// GOOD (Modern Industry Standard): Destructuring in the signature
function ProductCard({ name, price, image, isSale = false }) {
return (
<div>
{isSale && <span>SALE!</span>}
<h2>{name}</h2>
<p>{price}</p>
<img src={image} alt={name} />
</div>
);
}Common Pitfalls
- Forgetting the curly braces: If you write
function Card(title, desc), React will assign the entirepropsobject to the variabletitle, anddescwill be undefined. You must wrap them in braces to destructure:function Card({ title, desc }).
Interview Questions
You can assign default values directly during destructuring using the equals sign: function User({ avatar = 'default.png', name }). If the parent does not pass an avatar prop, it will safely fall back to 'default.png'.
The rest operator collects all remaining unspecified props into a new object. E.g., function Button({ variant, ...rest }). You can then spread those remaining props directly onto an HTML element: <button className={variant} {...rest}>. This is commonly used to pass down native HTML attributes like disabled, onClick, or aria-labels without manually declaring every single one.
Real-World Example
Forwarding Rest Props in a UI Library: When building design systems, you often want your custom components to accept all standard HTML attributes. By destructuring out the custom props (text, isLoading) and capturing the rest with ...rest, you avoid having to explicitly type out 50 different HTML attributes.
// Building a highly reusable UI button component
function PrimaryButton({ text, isLoading, icon: Icon, ...nativeButtonProps }) {
return (
// We spread all remaining props (like disabled, type="submit", onClick, aria-hidden) directly onto the native button
<button
className={`btn-primary ${isLoading ? 'loading' : ''}`}
disabled={isLoading}
{...nativeButtonProps}
>
{Icon && <Icon className="mr-2" />}
{isLoading ? "Loading..." : text}
</button>
);
}
// PARENT USAGE
// The parent can pass 'type', 'onClick', and 'aria-label' and they automatically flow through to the native <button> via ...nativeButtonProps
<PrimaryButton
text="Submit Payment"
isLoading={false}
type="submit"
onClick={processPayment}
aria-label="Pay now"
/>Check Your Knowledge
Test your understanding of Destructuring Props with these quick questions.