Looking at this React Router Dom v4 example https://reacttraining.com/react-router/web/example/auth-workflow I see that PrivateRoute component destructures a rest prop like this
const PrivateRoute = ({ component: Component, ...rest }) => (
<Route {...rest} render={props => (
fakeAuth.isAuthenticated ? (
<Component {...props}/>
) : (
<Redirect to={{
pathname: '/login',
state: { from: props.location }
}}/>
)
)}/>
)
I want to be certain that { component: Component, ...rest }
means:
From
props
, get the Component prop and then all other props are given to you, and renameprops
torest
so you can avoid naming issues with the props passed to the Routerender
function
Am I right?
Sorry, I realized my first answer (while hopefully still providing useful/additional context) doesn't answer your question. Let me try again.
You ask:
I want to be certain that
{ component: Component, ...rest }
means:From
props
, get theComponent
prop and then all otherprops
given to you, and renameprops
torest
so you can avoid naming issues with theprops
passed to the Routerender
function
Your interpretation is not quite correct. Based on your thoughts though, it sounds like you're at least aware of the fact that what is happening here amounts to some sort of object destructuring (see second answer and comments there for more clarification).
To give an accurate explanation, let's break down the { component: Component, ...rest }
expression into two separate operations:
component
property defined on props
(Note: lowercase component) and assign it to a new location in state we call Component
(Note: capital Component).props
object and collect them inside an argument called rest
.The important point is that you're NOT renaming props
to rest
. (And nor does it have to do with trying to "avoid naming issues with the props
passed to the Route render
function".)
rest === props;
// => false
You're simply pulling off the rest (hence why the argument is named that) of the properties defined on your props
object into a new argument called rest
. It's worth noting, by the way, calling it rest
is mostly just a convention. You could call it anything you want.
const myObj = {
name: 'John Doe',
age: 35,
sex: 'M',
dob: new Date(1990, 1, 1)
};
For this example, it may help to just think of props
as having the same structure (i.e., properties and values) as shown in myObj
. Now, let's write the following assignment.
const { name: Username, ...rest } = myObj
The statement above amounts to both the declaration and assignment of two variables (or, I guess, constants). The statement can be thought out as:
Take property
name
defined onmyObj
and assign its value to a new variable we callUsername
. Then, take whatever other properties were defined onmyObj
(i.e.,age
,sex
anddob
) and collect them into a new object assigned to the variable we namerest
.
Logging Username
and rest
to the console
would confirm this. We have the following:
console.log(Username);
// => John Doe
console.log(rest);
// => { age: 35, sex: 'M', dob: Mon Jan 01 1990 00:00:00 GMT-0800 (PST) }
Why not destructuring the properties from the props instead of using the reset parameter syntax
{prop1, prop2,...remainingProps}= obj
Imagine if we are creating an Input component as follows:
const Input ({label, id, type, onChange,value})=>{
return(
<label htmlFor={id}> {label} </label>
<input id={id} type={type} onChange={onChange} value={value}/>
)
}
At first, you might think this component is good, but actually, there are many other attributes to the input that we cannot add as a user for this component see a list of all input attributes here. So if we used the component as follows:
<Input id={myId} value={myValue} onChange={myOnChange} label={myLabel} type={myType} minLength={30} maxLength={100}/>
then in order to account for any additional props that we are passing we need to destructure them to pass them to the input, but we are actually using the label only and other props are delegated to the the input, so making the remaining props as ...rest
will count for any additional props that we pass to the component and add them to the corresponding component or element which will make our component count for more use cases.
You may also wonder :
Why go through the trouble of pulling off the
component
property only to rename itComponent
with a capital letter "C"?
Yeah, it seems pretty trivial. And, while it is a standard React practice, there's a reason all of Facebook's documentation on its framework is written as such. Namely, capitalizing custom components rendered with JSX is less a practice per se than it is a necessity. React, or more properly, JSX is case-sensitive. Custom components inserted without a capitalized first letter are not rendered to the DOM. This is just how React has defined itself to identify custom components. Thus, had the example not additionally renamed the component
property that was pulled off of props
to Component
, the <component {...props} />
expression would fail to render properly and would render a <component />
element in the DOM, not the actual React component.