Extra arguments to function components in React

I’m trying to delve deeper into the React universe, and I’m seeing something I don’t completely understand, nor can’t find any relevant explanation in the reactjs docs. Maybe it’s something related to JS in general and not specific to React, like ES6 syntactic sugar that I can’t link to this at the moment.
Anyway, I see that sometimes people pass more arguments to functional components than just props, and sometimes they don’t even pass props but just other arguments. When they do, extra arguments and props are wrapped in curly braces.
An example could be @sitek94 React Drum Machine, for instance in the PadBank.js file:
export default function PadBank({ sounds, …props }) {…}.
I don’t exactly understand the purpose of this: why should we pass something to a child component as some extra argument outside the props argument? Also, why do we need to wrap everything inside curly braces? I’d really appreciate it if anyone could point me to some relevant docs.

You use it when you are making a component that should behave exactly the same as some existing component but with some additional functionality. It’s unusual in most cases, but it’s extremely common in component libraries (things like React Bootstrap or React Material UI). So you get things like:

const Button = React.forwardRef(({ specialProp, ...props }) => {
  // DO SOMETHING WITH SPECIALPROP 
  // HERE, THEN:
  return <button ref={ref} {...props}>{props.children}</button>;
}));

And instead of <button>, you use <Button> and they act the same except the latter has some special component library functionality added to it.


Re {...props}, that’s the object spread syntax. It looks weird when it’s used like <button {...props}>, but it works because:

  • props is an object
  • <button> desugars to React.createElement("button", /* props */, /*children */).
  • so <button ref={ref} {...props}> desugars to something like React.createElement("button", { ref, ...props}, null)

Edit: YMMV, but it isn’t advisable to overuse that way of passing props. It sometimes seems like a nice easy way to pass stuff around, but unless you’re writing a component library (or simply creating a component that needs to have everything an existing component ± some small thing) you almost always want to pass props explicitly – it’s quite confusing to read as it means you’re passing stuff implicitly, it passes everything so you’ll often get props you don’t want, and it’s easy to make the error of not putting it last in the props

1 Like

Thank you for this detailed explanation! :pray:
I’m beginning to see some light now.

1 Like

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.