You can find a summary of the code updates in this pull request . Read on for explanations.
1. Name the un-destructured props
To collect all the props that aren’t explicitly destructured, use this syntax (as described by MDN ):
...delegated
is not a special name; you can use whatever variable name you wish instead (for example, ...theRestOfTheProps
). However, ...delegated
is conventional because these props are being “delegated” from the component to its top level element.
Destructuring the functional component argument looks like this:
Button.tsx
An example
With this syntax, if the component declaration looks like this:
then delegated
would evaulate to an object with all the props except the explicitly declared variant
and children
:
2. Delegate props
The syntax for passing along the un-destructured props is (perhaps confusingly) similar. The delegated
object can be spread into individual props, like this:
Button.tsx
(reference: React docs for props spreading )
Example return value
For the same example <Button>
declaration example above, the equivalent attributes in the return value would look like this:
3. Props conflicts
Note that {...delegated}
is specified after all the other props. That means the values from delegated
will have the last word over any props that were declared previously. Consider this example:
Button.tsx
Let’s say Button was declared like this (other props omitted for brevity):
Then the component would render as:
(Note, the rpDYh
string will vary, but Button_wrapper__<random-string>
is the general format of CSS modules rendered class names.)
There are two class attributes here:
"Button_wrapper__rpDYh"
, from the attribute in the returnedbutton
element, and"snazzy"
(from theButton
declaration).
Guess which one’s going to win? The second one. The second attribute will clobber the first one, as though we were living in a world where class="Button_wrapper__rpDYh"
never existed.
The way to remedy this is to explicitly destructure any props that will clash with props you are using, and combine the values. Here’s how that looks with className
(using clsx for ease of class combining):
Button.tsx
className
is the only potential clash for either of our components at the moment, but we will revisit this concept in a future workshop (when we add a style
prop to the Card
component’s article
element).
Note: All of the work we did for prop delegation in the Button
component can (and should!) be applied to the Card
component.
Up next
With all the props work done, the next workshop will tackle styling for the Button
variants.