57

When passing props should I pass the entire object into the child components or should I individually create props first in the parent component and then pass those props to the child?

Pass entire object:

<InnerComponent object={object} />

Individually create props that're needed first:

<InnerComponent name={object.name} image={object.image} />

Which one is preferred and if it depends, what should I use as a gauge to use either?

catandmouse
  • 11,309
  • 23
  • 92
  • 150

9 Answers9

34

According to the principle of least privilege, this is a correct way:

<InnerComponent name={object.name} image={object.image} />

This restricts InnerComponent from accidentally modifying original object or accessing properties that aren't intended for it.

Alternatively, properties could be picked from original object and passed as props:

<InnerComponent {...pick(object, 'name', 'image')} />

If there are numerous properties that are tedious to list, there may be single prop that accepts an object:

<InnerComponent object={pick(object, 'name', 'image')} />
Estus Flask
  • 206,104
  • 70
  • 425
  • 565
  • 7
    maybe nice to add that pick is a function from lodash. Since generating a subset of an object is pretty straight forward in JS when you want something like { name: name } it would be possible to omit pick() and simply use {name, image}, I guess ... – Xen_mar Nov 27 '19 at 08:12
  • @Xen_mar Lodash is a notable example but it's arbitrary picking function, could be user-defined one-liner, `pick = (o, ...keys) => Object.fromEntries(Object.entries(o).filter(([k]) => keys.includes(k)))`. Destructuring requires to have `let {name, image} = object` above which is not always practical due to how JSX is usually written, it could be an arrow with no `return`. – Estus Flask Nov 27 '19 at 09:28
28

You should prefer your second example, to pass the props individually. There you can see explicitly which arguments are passed and can quickly compare with which arguments are expected. This makes collaboration along people much easier and makes the state of the application more clear.

I personally try to avoid passing whole objects if it's not needed. It's like the spread operator where there can be any property inside and it is much harder to debug in a bigger scope.

Some additions to pure react like prop-types or typescript might help to define clear and expected properties in a big application

mstruebing
  • 1,674
  • 1
  • 16
  • 29
  • 8
    So it is a matter of maintainability? Does React suffer from any noticeable overhead from passing objects down instead of properteies? – gafemoyano May 20 '19 at 15:14
13

Since JavaScript has no type annotation, the second choice would be much preferable, as mentioned by @mstruebing the code will be more maintainable. However, if you are using TypeScript React (which support type annotation), both choice would be equally clear. But do keep in mind, the first choice promotes tight coupling between views and models, this allows fast development as you don't have to type much; while the second choice might slows down development but you have higher flexibility and tolerance to future changes.

So, the gauge is: if you favor development speed over flexibility, go for choice 1; if you favor flexibility over development speed, go for choice 2.

Extra notes

Ok, when should we favor development speed over flexibility? Here's my 2 cents.

If your project was meant for short-term usage (for example developing an app just for collecting votes during election), then go for the first choice.

If your project was meant for long-term usage (for example online bank transaction portal), you should go for the second choice.

Wong Jia Hau
  • 2,639
  • 2
  • 18
  • 30
  • 1
    Also my 2 cents: by experience, I think it is generally worth taking the time to go for choice 2 as it is not _that_ longer than choice 1. You'll save a great amount of time the day you realize your app is no longer for short-term usage (it almost always ends up like this) – Ian Letourneau Oct 11 '19 at 18:00
2

Passing multiple props to a child component is the preferred way of passing props to child components. This will help you in tracking the state of the application in the child component. Also, feel free to use the prop-types module. It acts like generics in Java and provides type safety for the props to pass in.

Souvik Dey
  • 653
  • 1
  • 9
  • 18
2

If you aren't making use of all the properties within the object, its better to pass the required properties separately as it can help in performance optimisation when the Child component is a PureComponent of use shouldComponentUpdate. In such a case, only when the props used by the Child component change, its will re-render and not when an unused property from within the object has changed.

However if your are making use of all the properties within the object, it doesn't make much of a difference event if you pass down the object as a props, provided you handle the mutations of the object correctly.

Shubham Khatri
  • 270,417
  • 55
  • 406
  • 400
  • if we are passing an object, the re-render would only depend on when the whole object changes and not on the individual properties – gaurav5430 Jun 22 '21 at 13:56
2

I agree with the other answers that in short, it depends, and the points raised in other answers are all valid.

Some other points I would like to add that also leans towards using individual properties are as follows -

  • Sometimes its not even the question of whether Do I need all the properties? It should be more of the question - Do I want to restrict the usage of the component to when I only have the complete object and not just a subset of properties.

Take for example a widget to display a car's image, make and model as part of a list of a widgets, its not reasonable to expect the full Car type to be available in order to display only the car's image, make and model. Only those 3 properties are required.

  • With the likes of rise of the likes of graphql where we can restrict the properties of data being returned about a type, we shouldn't always assume that components will have access to fully populated objects based on a type.

  • Lastly on the point of causing unnecessary rerenders of components down the tree, always passing the full object around, you are likely to cause all children that consumes that object will rerender when the object is updated. However passing separate properties to children, usually primitives, we can better mitigate against unnecessary rerenders

andy mccullough
  • 9,070
  • 6
  • 32
  • 55
  • Regarding your last point on unnecessary rerenders. If the prop changes, doesn't it mean that the parent component updates it? It updates this prop due to its state got changed, which led parent component to re-render. So it rerenders anyway, and renders the child, regardless of whether we pass the whole object or part of it as a prop, doesn't it? My question is: do rerenders really depend on parent->child prop type (object, primitive)? – Aleksi Baklanov Apr 04 '22 at 09:33
  • 1
    Not necessarily, if a a parent rerenders and a child (that uses `memo`) receives the same props as before (that is same primitive value or same object / array reference) it wont rerender the child. My point is that it is much safer to shallow compare primitive values as props, and therefore guard against deep, unnecessary rerenders, whereas passing objects and arrays as props, it is much easier to accidentally pass a new object / array reference as a prop and in that case the child _will_ rerender – andy mccullough Apr 04 '22 at 11:05
  • Now I see what you mean. Yes, I agree. – Aleksi Baklanov Apr 04 '22 at 12:37
2

The whole point of objects is to encapsulate similar properties together. If you have about 10 properties and want to use them in your child component, stick with objects.

But in your case, my opinion is to use your second example as it makes the code in the child component simpler.

To the best of both worlds simply destructure those props that you need inside your child component.

Like this:

function InnerComponent({ name, image }) {
  ...
}

If you don't like braces in the arguments do this:

function InnerComponent(props) {
  const { name, image } = props;
  ...
}
1

It depends on that Object. Do you need ALL of its properties to be passed to another component? Or... You might need to pass 2 properties out of 5 to a specific component?

  • If you don't need to pass ALL of its properties, I recommend passing the Properties as Props
  • BUT, if you are 100% sure that you NEED ALL THE PROPERTIES to be passed together, I recommend passing the whole Object as Props in that case as it would be much clearer code and keeps you away from forgotten to pass something. For example; When you add a new property to that object, you don't have to pass it, as you are already passing the whole Object!

Well, if you aren't certain about your current/future purpose of that Object as you might need to EXCLUDE some properties soon, you probably should pass its properties individually in that case, instead of passing some non-used properties to the other component.

Elharony
  • 886
  • 8
  • 18
-3

You can pass props into JSX element as single object using React.createElement function.

Because each JSX element is just syntactic sugar for calling React.createElement.

The following 2 lines are equal for React:

<Button variant={"secondary"}>Add</Button>
{React.createElement(Button, {variant: "secondary", children: "Add"})}
James Bond
  • 2,229
  • 1
  • 15
  • 26