0

I have the following React component:

export default function AuthExample () {
  return (
    <Router>
      <div>
        <AuthButton/>
        <ul>
          <li><Link to="/public">Public Page</Link></li>
          <li><Link to="/protected">Protected Page</Link></li>
        </ul>
        <Route path="/public" component={Public} />
        <Route path="/login" component={ Login } />
        <PrivateRoute path='/protected' component={ Protected } />
      </div>
    </Router>
  )
}

My difficulty is understanding the parameters passed to the component and how it is being unboxed in the function that creates this component , below is the function:

const PrivateRoute = ({ component: Component, ...rest }) => (
  <Route {...rest} render={(props) => (
    fakeAuth.isAuthenticated === true
      ? <Component {...props} />
      : <Redirect to={{
          pathname: '/login',
          state: { from: props.location }
        }} />
  )} />
)

So what exactly is component: Component here ? and is the ES-5 destructive assignment ? so then what exact is <Component {...props} /> in the end ?

Alexander Solonik
  • 9,838
  • 18
  • 76
  • 174
  • It's not called "destructive assignment". It's _destructuring assignment_. "destructive" implies that something is destroyed, but in fact destructuring assignment is a useful way to avoid mutating the original object or array. So in a sense it's the opposite of destruction. – Håken Lid May 13 '19 at 19:43

3 Answers3

1

The { component: Component, ...rest } assigns property component to variable Component. You can read about destructuring assignments here.

In the <PrivateRoute path='/protected' component={ Protected } /> you pass Protected as a component property and Protected is then referenced as Component variable inside PrivateRoute component. This is only for your convenience. This is required by JSX in order to distinguish between standard html elements and user-defined components.

In <Component {...props} /> the {...props} means to take all the key-value pairs from props object and pass them to the Component. Check out this stackoverflow answer for better clarification.

In fact, the following line

const PrivateRoute = ({ component: Component, ...rest }) => ();

means

from the properties passed to this component take the component, store it as Component and keep all other properties in rest variable.

mrJoe
  • 500
  • 3
  • 13
1

You first passed to PrivateRoute the following two props: path and component. What the function header ({ component: Component, ...rest }) means, is that you can pass it an object, and it will look for a property with the key of component and store it as Component, and the rest of the remaining properties, if any, will be put into the rest object. In this case, your component parameter will be the component Protected, which you passed, and the rest will contain the path.

Regarding <Component {...props} />: It's object destructuring, which basically means, that the key: value pairs within that object, in your case props, will get enlisted there.

So, with an object:

const myProps = {
    name: 'John',
    age: 21
}

And used as:

<MyComponent { ...myProps } />

It's the same as you would do this:

<MyComponent name={myProps.name} age={myProps.age} />
  • 1
    "it will look for a property with the key of component and a type of Component" - this is not true. The point of that line is to store a `component` as `Component`. It says nothing about the type of this property. – mrJoe May 13 '19 at 19:43
  • You are correct, I was thinking in TS, thank you. Updated answer. – Stefan Szakacs May 13 '19 at 19:47
1

{component: Component} is indeed destructuring assignment, also called "argument unpacking" in the context of function arguments.

It simply gives the prop component a new name Component in the scope of this function. JSX syntax requires all user defined components to be capitalized. (<component /> will not work. Only native dom elements can be lower cased: <span /> etc.)

While it's syntactically permitted to use any case in prop names (so you could simply use { Component } instead, the convention for props is to use camelCase, following normal javascript convention for DOM attributes and variable names.

So the prop you pass in is called component, but inside the component function, it's Component.

Håken Lid
  • 22,318
  • 9
  • 52
  • 67