DEV Community

Cover image for Polymorphism with React
Helder Burato Berto
Helder Burato Berto

Posted on • Edited on • Originally published at helderberto.com

Polymorphism with React

In this article, we will create an example using Polymorphism in React.

Acceptance Criteria

  • Create a LinkButton that render an element button or a depending on the href prop
  • The LinkButton component has an optional prop called href
  • If the href is provided, the component should render an a tag. Otherwise, it should render a button 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>
}
Enter fullscreen mode Exit fullscreen mode

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>
}
Enter fullscreen mode Exit fullscreen mode

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>
  )
}
Enter fullscreen mode Exit fullscreen mode

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)

Collapse
 
brense profile image
Rense Bakker

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.

Collapse
 
gilfewster profile image
Gil Fewster

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.