Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pass several props in spread operator in react

Tags:

reactjs

I have the following:

let objA = {varA,varB};
let objB = {varC, varD};

I'd like to pass varA,varB,varC,varD to my component, but not one by one because the number of variables inside objA and objB should be unknown.

I've read in react docs that this is possible with spread operator:

let bothObjects = {...arrA, ...arrB};
<Component {...bothObjects} />

But is it possible to do without the third object?

This works:

<Component {...objA} {...objB} />

But I'm not sure it's correct... This also works:

<Component {...{...objA,...objB}} />

But it looks funny and I don't fully understand this.

This, however, does not work:

<Component {...objA, ...objB} />

and I'm not sure why... because it worked when I initialized 'bothObjects' above... It also looks to my like the proper way to do it intuitively.

Where am I mistaking?

like image 221
Poogy Avatar asked Mar 24 '18 21:03

Poogy


4 Answers

First a look in JSX. When you do (scenario 1):

<Component myProp={something} />

The something typically is a JavaScript expression.

When you use the spread operator, like (scenario 2):

<Component {...something} />

Then something should be a JavaScript object.

Your case

Considering objA and objB are two JavaScript objects, you can use them like scenario 2 above:

<Component {...objA} {...objB} />

And they should work as expected.

When you do:

let bothObjects = {...objA, ...arrB};
<Component {...bothObjects} />

Again, it works because bothObjects is too an object. Just one object that happens to have been built based on objA and objB.

The other case:

<Component {...{...objA,...objB}} />

May seem weird, but works perfectly. See, from scenario 2 above, JSX expects (in {...something}) that something is an object. And {...objA,...objB} is an object. Well, it's actually an expression that "returns" a value of object type, but it's the same. It works fine.

The last case:

<Component {...objA, ...objB} />

Does not work because the expresion objA, ...objB is not a JavaScript object. It actually means nothing, it is a syntax error. See the error message:

VM2296 babel.js:17994 Uncaught SyntaxError: Babel script: Unexpected token, expected }
  30 | 
  31 |       <Bob
> 32 |         {...objA, ...objB}
     |                 ^

As you can see, after the char A of ...objA, JSX just expected to find the }. But it found a , which is an error (Unexpected token).

What to use?

Considering all three forms that work:

let bothObjects = {...objA, ...arrB};
<Component {...bothObjects} />
<Component {...objA} {...objB} />
<Component {...{...objA,...objB}} />

To say which one is better is just a matter of taste. Pick whatever you think is more readable.

like image 86
acdcjunior Avatar answered Oct 19 '22 07:10

acdcjunior


Rest parameters should be the last named argument of a function, you're passing two. You should divide both into separate props, like in your working example:

<Component {...objA} {...objB} />

In this example you have two props, the with Rest parameter is the first one.

function sum(...theArgs, q) {
 return theArgs.reduce((previous, current) => {
    return previous + current;
  });
}`

When I put the a parameter it gives me the error:

Error: parameter after rest parameter

EDIT: And @Omar is right, in this case there's no need for using Rest Parameters, since both are simple objects

like image 41
Tico Avatar answered Oct 19 '22 08:10

Tico


If you have the following

let objA = {varA,varB}; let objB = {varC, varD};

To pass these as props you simply do

<Component objA={objA} objB={objB} />

Theres no reason to use ... syntax.

Simply acess them in the component with this.props.objA or this.props.objB. You can then do whatever you want with these objects in the respective component you passed it down to.

like image 35
Omar Avatar answered Oct 19 '22 08:10

Omar


This was my use case. Changing some props from a defined object:

<Component someProp={{...{...someObject, ...{someValue: false}}}} />
like image 1
Emi Avatar answered Oct 19 '22 06:10

Emi