React ES6 Destructuring
Destructuring unpacks values from objects and arrays into individual variables, and it's the standard way React reads props.
Object destructuring
Object destructuring pulls named properties off an object into local variables in a single statement, matching by property name rather than position. You can rename variables, provide default values for missing properties, and destructure nested objects in one expression.
Object destructuring basics
export default function App() {
const user = { id: 7, name: 'Priya', role: 'admin' };
const { name, role } = user;
console.log(name, role); // "Priya" "admin"
// Renaming while destructuring
const { name: displayName } = user;
console.log(displayName); // "Priya"
// Default value for a missing property
const { theme = 'light' } = user;
console.log(theme); // "light" (not present on `user`, so default is used)
return (
<div>
<p>name: {name}</p>
<p>role: {role}</p>
<p>displayName: {displayName}</p>
<p>theme: {theme}</p>
<p>Open the console to see the logged values.</p>
</div>
);
}Array destructuring
Array destructuring unpacks by position instead of name, which is exactly why useState's return value — a two-element array of [value, setter] — is destructured rather than accessed by index.
Array destructuring, including useState
import { useState } from 'react';
const coordinates = [12.5, 47.9];
const [lat, lng] = coordinates;
console.log(lat, lng); // 12.5 47.9
// Skipping elements with commas
const [first, , third] = ['a', 'b', 'c'];
console.log(first, third); // "a" "c"
// The pattern behind useState
function Counter() {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(count + 1)}>{count}</button>;
}
export default function App() {
return (
<div>
<p>lat: {lat}, lng: {lng}</p>
<p>first: {first}, third: {third}</p>
<Counter />
<p>Open the console to see the logged values.</p>
</div>
);
}Destructuring props
React components receive a single 'props' object as their argument. Destructuring it directly in the function signature is the idiomatic way to declare which props a component expects, and it doubles as lightweight documentation.
Destructuring props in a function signature
// Without destructuring — has to repeat `props.` everywhere
function UserCard(props) {
return <h2>{props.name} ({props.role})</h2>;
}
// With destructuring, including a default value and renaming
function UserCardBetter({ name, role = 'member', id: userId }) {
return (
<h2 data-user-id={userId}>
{name} ({role})
</h2>
);
}
export default function App() {
return (
<div>
<UserCard name="Priya" role="admin" />
<UserCardBetter name="Sam" id={42} />
</div>
);
}Destructuring also works with nested structures and the rest pattern, which collects the remaining properties or elements that weren't explicitly pulled out. This is common when a component needs a few specific props but should forward everything else to an underlying DOM element.
Nested destructuring and the rest pattern
function Avatar({ user: { name, imageUrl }, size = 'medium', ...rest }) {
return (
<img
src={imageUrl}
alt={name}
className={`avatar avatar--${size}`}
{...rest}
/>
);
}
export default function App() {
// Usage: extra props like onClick flow through via {...rest}
return (
<Avatar user={{ name: 'Sam', imageUrl: '/sam.png' }} onClick={() => {}} />
);
}- Object destructuring matches by property name; array destructuring matches by position.
- Default values only apply when the value is 'undefined', not for null or 0.
- The rest pattern (...rest) must come last and collects everything not already destructured.
- Destructuring in a function parameter list destructures the argument as soon as the function is called.
Exercise: React ES6 Destructuring
What does writing `function Welcome({ name, age })` do with the incoming props object?