3

so as I understand it, this {...props} is the same things as {prop1, prop2, prop3}

When declaring a stateless functional component, it is convenient to utilize destructuring so that you don't have to constantly type props.prop1, props.prop2 etc. However, when you have 10+ props you need to pass down to your child component things can get very ugly so I thought that I could just use the spread operator to destructure my props object!

Based on the idea that {...props} is essentially the same as {prop1, prop2, prop3} I expected the below code to work, but I get a prop1 is undefined error

const Component = ({...props}) => {
    return (
        <div>
            {prop1}
        </div>
    )
}

is what I'm trying to do possible? I couldn't find any examples online, but it would be awesome if there was a way to destructure the props object without explicitly listing every prop!

EDIT: Please understand I know how to properly access properties from the props object. Read my question more carefully, I am trying to spread all the properties in the props object, similar to declaring them explicitly example:

const Component = ({prop1, prop2, prop3}) => {
    return (
        <div>
            {prop1}
        </div>
    )
}

I expect that could to behave the same as if I initialize the component with {...props}

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
Robbie Milejczak
  • 5,664
  • 3
  • 32
  • 65
  • 1
    `props` is actually an object, so you'd need to access it as such : `props.prop1` – Mark C. Oct 26 '17 at 19:27
  • yes of course, but if I destrucure is as ({ prop1 }) I can access prop1 explicitly. So I expect the spread operator to create similar behavior, but it does not – Robbie Milejczak Oct 26 '17 at 19:29
  • 1
    "*as I understand it, `{...props}` is the same things as `{prop1, prop2, prop3}`*" - well, **no**. If you want to destructure to individual variables, you need to do so explicitly. Write what you actually meant. – Bergi Oct 26 '17 at 19:34
  • 3
    First of all, there is no "spread operator". Second of all you are not spreading anything here. `{...props}` in this context means that all *remaining* ("rest") properties of the object passed as argument should be *collected* in a new object assigned to `props`. Therefore `({...props}) => {}` is basically the same as `props => {}`, so you are not gaining anything. If you wrote `{prop1, ...props}` instead it would be different. This would extract `prop1` from the passed object and assign it to variable `prop1` and would assign `prop2` and `prop3`) to a new object assigned to `props`. – Felix Kling Oct 26 '17 at 19:40
  • you can pass the props to the child and you can do destructing the props of this sort `const { prop1, prop2, prop3 } = props;` – RamaKrishna Oct 26 '17 at 19:40
  • @FelixKling woah not sure why but I am sensing some hostility from you. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator what is that then if there is no spread operator? – Robbie Milejczak Oct 26 '17 at 19:43
  • See https://stackoverflow.com/q/37151966/218196 and https://stackoverflow.com/q/44934828/218196 . In this instance, `...props` denotes a **rest property**. – Felix Kling Oct 26 '17 at 19:44
  • @FelixKling so is it possible to do what I'm attempting to do? Assign each prop to it's own independent value without doing so explicitly? – Robbie Milejczak Oct 26 '17 at 19:55
  • @RobbieMilejczak: No, that's not possible. You have to explicitly define variables. – Felix Kling Oct 26 '17 at 19:55
  • 1
    Well for completeness sake, you basically want the `with` statement, as explained in [Destructuring an object without specifying its properties](https://stackoverflow.com/q/36797532/218196), but the `with` statement is deprecated, doesn't work in strict mode and ES6 modules are strict. – Felix Kling Oct 26 '17 at 20:00

1 Answers1

1

this {...props} is the same things as {prop1, prop2, prop3}

This is only true if you your function parameters deconstruct the object's properties by key value.

What I mean :

const doAThing = ({ prop1, prop2, prop3 }) => { console.log(prop1) }

And then calling it like doAThing({...props}) (where prop1 is a property on the props object) - In this scenario, you'd be correct. This is how it would work.

The reason you can't access prop1 like you're attempting to is because you haven't given the deconstruction assigment anything to assign to. It's just sitting there as the Object with the key/value pairs of prop1, prop2, prop3 etc..

Mark C.
  • 6,332
  • 4
  • 35
  • 71
  • see Viveks answer to my question, and note I am referring specifically to functional components in react, not regular es6 functions. If I explicitly declare an object called props, and pass it in as a prop and init the component with ({...props}) the behavior works as expected. However if I attempt to do this on the props object created by React it does not work. This is where I am confused – Robbie Milejczak Oct 26 '17 at 19:40
  • So your question is about Components that derive from the `React.Component` base class and not about the Object deconstructuring assignment functionality? – Mark C. Oct 26 '17 at 19:44
  • yes correct, as I understand it when I define a component all the properties I pass are collected into a props object and can be reference as props.prop1 etc, so I'm confused as to why I can't spread that object instead of explicitly destructuring it – Robbie Milejczak Oct 26 '17 at 19:47
  • @RobbieMilejczak: As I mentioned in my other comments, `...props` in this context is a *rest property*, not a *spread property*. It *collects* properties, it does not *spread* them. A *spread property* exists only in objects literals, e.g. `var point1 = {x: 0, y: 0}; var point2 = {...point1, x: 1}`. In this case the properties of `point1` are "spread into" `point2`. But you cannot use spread properties to implicitly create local variables. – Felix Kling Oct 26 '17 at 19:51
  • yep I already got my answer from you but I try not to make pointless comments, thank you for clearing it up though. I only thought the ... syntax did one thing – Robbie Milejczak Oct 26 '17 at 19:51
  • The spread (`...props`) is what ships the properties in the function execution and allows those properties to be deconstructed (unpacked) into parameters for the function. On the other hand, you'd have to explicitly ship the properties to the function `doAThing(props.prop1, props.prop2)` etc – Mark C. Oct 26 '17 at 19:52
  • @RobbieMilejczak: No, `...` has a different meaning in different contexts. Which is why I said that there is no single "spread operator". I detailed this in one of the questions I linked to in the other comment. We can distinguish between: Spread element (`[1, ...arr]`), rest element (`var [foo, ...bar] = arr;` and `([foo, ...bar]) => {}`), spread argument (`foo(...args)`), rest arguments (`(...args) => {}`). These are all part of ES6. The object rest/spread proposal adds rest properties (`var {foo, ...bar} = obj` and `({foo, ...bar}) => {}`) and spread properties (`{foo: 42, ...obj}`). – Felix Kling Oct 26 '17 at 19:58