Using ...rest to Remove Properties from an Object
Posted 2021-02-02
tl;dr The rest syntax allows you to pull attributes out of your props when you want to pass /almost/ all of them to another component with the spread operator.
const { attribute, ...rest } = props; return <Component {…rest} />
Sometimes an object will have most of the properties I want to forward to another component. For example, consider this component for a blog post page:
interface Props {
title: string;
body: string[];
tags: string[];
}
export const Page = (props: Props) => {
return <div>
<h1>{props.title}<h1>
{props.body.map(paragraph => <p>{paragraph}</p>)}
</div>
}
Suppose I wanted to add a component to manage SEO tags for this page. An abbreviated version of that component could be something like this:
interface Props {
title?: string;
body?: string[];
keywords?: string[];
}
export const SEO = (props: Props) => {
return ...
}
It could then be added to page like so:
export const Page = (props: Props) => {
return <div>
<SEO {...props} />
...
Passing {…props}
works, but there’s a catch. Instead of calling them tags
, SEO
calls them keywords
. Spreading the props this way results in an empty keywords
prop. For this, the rest syntax can help out.
Before passing props
into SEO
, I’ll destructure the problematic attribute out of props
. Now there are two variables: tags
and rest
. rest
contains title
and body
, which I can spread into SEO
unchanged. Finally, I pass in tags with the correct name.
export const Page = (props: Props) => {
const {tags, ...rest} = props; <-- rest destructuring
return <div>
<SEO keywords={tags} {...rest} />. <-- correct name
<h1>{props.title}<h1>
{props.body.map(paragraph => <p>{paragraph}</p>)}
</div>
}
If the SEO
component is under my control, I could just change keywords
to tags
. That’s honestly the simplest route. But sometimes you have to work with what you got, and it’s cases like these where the rest syntax can lend a hand.