React + TypeScript: Implementing the Polymorphic Button Component
A passionate web developer with a focus for continuous growth & delivering exceptional results.
Search for a command to run...
A passionate web developer with a focus for continuous growth & delivering exceptional results.
No comments yet. Be the first to comment.
Testing plays a crucial role in the development of robust and reliable applications. When building web applications, particularly those that rely on external APIs, testing API calls becomes essential to ensure the functionality of the application und...
Have you ever been bothered by those disruptive jolts when scrolling, especially while opening a modal? Fear not! Enter the CSS property scrollbar-gutter—a clever solution to mitigate these unwarranted movements triggered by the appearance or disappe...
If you've encountered the error useHref() may be used only in the context of a <Router> component while trying to integrate Remix's <Link /> component into Storybook, fear not. In this guide, we'll walk through a solution that involves creating a dec...
As developers, creating reusable and flexible components is a crucial aspect of building scalable applications. One powerful technique to achieve this is by developing polymorphic components.
In this article, we'll explore how to create a polymorphic component in React using TypeScript, providing a versatile solution for various scenarios.
A polymorphic component is one that can adapt its rendered element based on the context or specific requirements. In React, this flexibility is achieved by leveraging TypeScript generics. Let's dive into a practical example using a Button component.
import React, { ElementType, ComponentProps, PropsWithChildren } from 'react';
export type ButtonProps<AS extends ElementType> =
PropsWithChildren<{
as?: AS;
}> &
Omit<ComponentProps<AS>, 'as'>;
const Button = <AS extends ElementType>(props: ButtonProps<AS>) => {
const {
as: Element = 'button',
children,
...attrs
} = props;
return (
<Element {...attrs}>{children}</Element>
);
};
The above TypeScript code defines a ButtonProps type, utilizing TypeScript generics to make the component polymorphic. Let's break it down:
AS extends ElementType: This generic type parameter allows us to specify the element type that our button should render. It extends the ElementType from React, ensuring that only valid HTML elements or React components can be used.
PropsWithChildren: This is a utility type that ensures our component can accept children.
{ as?: AS }: The as prop is the key to making our component polymorphic. It allows us to specify the element type we want the button to render as. If not provided, it defaults to the standard button HTML element.
Omit<ComponentProps<AS>, 'as'>: This utility type is used to exclude the as prop from the props of the specified element type. This is a workaround to achieve the polymorphic behaviour.
Breaking down the Button component:
The as prop is destructured with a default value of 'button'. This default ensures that if no specific element is provided, the button will render as a standard HTML button.
The component then uses JSX to render the specified element, passing along the rest of the props (...attrs) and rendering the children within it.
Now that we have our polymorphic Button component, let's explore how to use it in different scenarios:
<Button onClick={() => alert('Clicked!')}>Click me</Button>
<a>) Element<Button as="a" href="https://example.com">Visit Example</Button>
In this article, we've explored the creation of a polymorphic Button component in React using TypeScript. The flexibility provided by polymorphism allows us to adapt the component to various use cases seamlessly.