What Are the Tradeoffs of Passing Objects as React Props?
- 3 minutes read - 488 wordsA common React pattern is to pass an object as a prop. Let’s consider the ways this can be used and tradeoffs of each.
Consider a user avatar component that shows the user’s initials. You might see one in the upper right of your screen right now.
What pieces of a user model should we pass to an Avatar
component to achieve
this?
- The initials? (
"JW"
) - The first and last names of the user? (
"Jake Worth"
) - Or should we pass the entire user object? (
user
)
Read on to see each in detail.
Passing Just the Initials
We could pass just the initials.
<Avatar
initials={user.firstName[0] + user.lastName[0]}
/>
The advantage of this approach is that the component gets what it needs– the initials– and nothing else. It lets the component be dumb, saying: “I receive initials, which I know nothing about, and I show them.”
Passing the Names
We could also pass the names that comprise the initials.
<Avatar
firstName={user.firstName}
lastName={user.lastName}
/>
The advantage of this approach is that we aren’t manipulating user
quite as
much in the parent, and instead sending down what we need to the component and
letting it build the initials.
Passing the Entire Object
We could pass the entire object!
<Avatar
user={user}
/>
This approach is potentially forward-thinking. Very often the component will end up needing more pieces of the user, such as a full name to show as a title, a background color that the user has selected, or an image URL. Passing the object could be pragmatic.
Passing More Than One of These
We could also pass multiple of these.
<Avatar
initials={user.firstName[0] + user.lastName[0]}
user={user}
/>
Components can drift into this pattern over time, and it’s the indefensible choice in this post. Passing an object and a string derived from it is redundant! It forces both the parent and the child to be smart about the object. We don’t want that.
So, Which Should I Choose?
I’m partial to passing the object. Practically, Avatar
almost always ends up
needing more pieces of the user over time. I think the pragmatic choice is to
concede that from the start and pass the object.
YAGNI (You Aren’t Going to Need It) is the first counterargument, and I’m sympathetic. However, often in production you are going to need it.
Reusability is the second counterargument. What if we want to pass pieces of different kinds of objects to the component? Initials-only supports this– it’s just strings. I think this aspiration is imagined more than it is realized in production code, but it could be the right choice.
Conclusion
Thanks to Gabe Reis who shaped my thinking on this during a year of building frontends together at Hashrocket.
🎉 Update: Adam Young responded to my post! He brought up some excellent points: how initials could be built in the ‘M’ of MVC, why displaying them can be a hard programming problem, and how to do it well.