In this article, we will create an example using Polymorphism in React.
Acceptance Criteria
- Create a
LinkButton
that render an elementbutton
ora
depending on thehref
prop - The
LinkButton
component has an optional prop calledhref
- If the
href
is provided, the component should render ana
tag. Otherwise, it should render abutton
tag
Solving the Problem without Polymorphism
import React from 'react'
export default function LinkButton({ href, children }) {
if (href) {
return <a href={href}>{children}</a>
}
return <button>{children}</button>
}
It solves our problem, but imagine if we need to pass the rest
of props to the component.
It will involve updating the button
and the a
, like the following example:
import React from 'react'
export default function LinkButton({ href, children, ...props }) {
if (typeof href === 'string') {
return (
<a href={href} {...props}>
{children}
</a>
)
}
return <button {...props}>{children}</button>
}
And for every case you want to add props, you gonna need to maintain both cases, so much work, right?
Solving the Problem with Polymorphism
Let's create the same example using Polymorphism:
import React from 'react'
export default function LinkButton({ href, children, ...props }) {
const Tag = typeof href === 'string' ? 'a' : 'button'
return (
<Tag href={href} {...props}>
{children}
</Tag>
)
}
You may be asking, and what about the href
being passed to the button
?
Since it will be undefined
React will take control to avoid rendering this property to our HTML.
Wrapping Up
Keeping this approach in mind, you can create a component that handles the logic you want, and it will be easier to give maintenance.
I hope this tip was useful for you!
Top comments (2)
You could take it a step further and do this with typescript. Add a "component" prop and based on its value (a, button, div, Custom component...) allow the user to provide any prop they would normally be able to use on that html element or custom component. The mui library actually did this. React offers some good ways to extract component/element props in typescript and this makes for a really nice developer experience when they use your component.
Not sure about this. Relying on React to deal with the undefined prop makes it harder to parse the intent behind the code.
I prefer to do something like use a generic prop called ‘target’ and then return link with target value as the href if target is a string, or a button with target as the onClick if target is a function.