How to create React UIKIT components in TypeScript that extends native HTML Elements

In the front-end ecosystem, UiKits are collections of utilities and several components, such as:

<Card />
<TabBar />
<Carousel />

<Row /> and <Col />

<GoogleMap />

Each component has usually its own custom layo…


This content originally appeared on DEV Community and was authored by Fabio Biondi

In the front-end ecosystem, UiKits are collections of utilities and several components, such as:

  • <Card />
  • <TabBar />
  • <Carousel />
  • <Row /> and <Col />
  • <GoogleMap />

Each component has usually its own custom layout and could accepts several properties. For example, a "Google Map" component could accept the "coordinates" and a "zoom" value as properties:

<GoogleMap coords={coords} zoom={zoom} />

Sometimes we need to create components whose layout is created from scratch. In other cases their layout may be based of native elements.
Some examples:

  • <MyButton />: that extends <button> element capabilities
  • <MyImg />: that extends <img> element
  • and so on.

Let's imagine a button component that must display an icon next to the label that I can use as shown below:

<MyButton icon="💩"> CLICK ME </MyButton>

This component should accept the icon and children properties and its definition may looks like the following:

interface MyButtonProps {
  icon: string;
}

function MyButton(props: PropsWithChildren<MyButtonProps>) {
  const { icon, children } = props;
  return <button className="btn btn-primary">
    {icon} {children}
  </button>
}

So we can use the component in this way:

<MyButton icon="💩"> DO SOMETHING</icon>
<MyButton icon="😱"> CLICK ME</icon>

OUTPUT

Button Preview

THE PROBLEM

In order to work fine, our MyButton component should also accepts all the native button properties. For example we may need to listen the onClick event or disabled it:

<MyButton icon="💩" onClick={...} disabled={...} />

So we should add them to the Component's Property Type and apply them as attributes of the <button> element:

// 1. Add the properties 
interface MyButtonProps {
  icon: string;  
  disabled: boolean;   // ➡️ native prop
  onClick: (e: React.MouseEvent) => void; // ➡️ native prop
  // ➡️ other native props
}

function MyButton(props: PropsWithChildren<MyButtonProps) {

  const { icon, children, onClick, disabled } = props;
  // 2. apply all props one by one
  return <button disabled={disabled} onClick={onClick} className="btn btn-primary">
    {icon}
    {children}
  </button>
}

Should I add all the HTMLButtonElement properties to the component type and apply them one by one? Nahh : )
That's too much work and I'm sure I'll forget some properties 😓

SOLUTION

What we can do to avoid all this work?
We can simply use an intersection type to combine our custom props with all the HTMLButtonElement properties to automatically support all native buttons properties:

export function MyButton(
  props: PropsWithChildren<MyButtonProps & React.ButtonHTMLAttributes<HTMLButtonElement>>
) { 
 // ... component here ...
}

Now your component supports all buttons properties and we can apply them simply using this trick:

// apply all props as button attributes
return <button className="btn btn-primary" {...props}>

However icon and children are not valid button's properties so we'll use the following "trick" (destructuring) to create a rest property that contain all the properties except icon and children:

  const { icon, children, ...rest } = props;

  // Now we apply all props except icons and children
  return <button className="btn btn-primary" {...rest}>
    {icon}
    {children}
  </button>

And that's all.
Here our final source code to create a button that support icon, children and all native button properties:

import { PropsWithChildren } from 'react';

interface MyButtonProps {
  icon: string;
}
export function MyButton(
  props: PropsWithChildren<MyButtonProps & React.ButtonHTMLAttributes<HTMLButtonElement>>
) {
  const { icon, children, ...rest } = props;
  return <button className="btn btn-primary" {...rest}>
    {icon}
    {children}
  </button>
}

USAGE EXAMPLE:

<MyButton 
  icon="💩" 
  type="submit"
  disabled={...} 
  onClick={...} 
  onMouseOver={...} 
> CLICK ME </MyButton>


This content originally appeared on DEV Community and was authored by Fabio Biondi


Print Share Comment Cite Upload Translate Updates
APA

Fabio Biondi | Sciencx (2022-07-08T21:50:24+00:00) How to create React UIKIT components in TypeScript that extends native HTML Elements. Retrieved from https://www.scien.cx/2022/07/08/how-to-create-react-uikit-components-in-typescript-that-extends-native-html-elements/

MLA
" » How to create React UIKIT components in TypeScript that extends native HTML Elements." Fabio Biondi | Sciencx - Friday July 8, 2022, https://www.scien.cx/2022/07/08/how-to-create-react-uikit-components-in-typescript-that-extends-native-html-elements/
HARVARD
Fabio Biondi | Sciencx Friday July 8, 2022 » How to create React UIKIT components in TypeScript that extends native HTML Elements., viewed ,<https://www.scien.cx/2022/07/08/how-to-create-react-uikit-components-in-typescript-that-extends-native-html-elements/>
VANCOUVER
Fabio Biondi | Sciencx - » How to create React UIKIT components in TypeScript that extends native HTML Elements. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2022/07/08/how-to-create-react-uikit-components-in-typescript-that-extends-native-html-elements/
CHICAGO
" » How to create React UIKIT components in TypeScript that extends native HTML Elements." Fabio Biondi | Sciencx - Accessed . https://www.scien.cx/2022/07/08/how-to-create-react-uikit-components-in-typescript-that-extends-native-html-elements/
IEEE
" » How to create React UIKIT components in TypeScript that extends native HTML Elements." Fabio Biondi | Sciencx [Online]. Available: https://www.scien.cx/2022/07/08/how-to-create-react-uikit-components-in-typescript-that-extends-native-html-elements/. [Accessed: ]
rf:citation
» How to create React UIKIT components in TypeScript that extends native HTML Elements | Fabio Biondi | Sciencx | https://www.scien.cx/2022/07/08/how-to-create-react-uikit-components-in-typescript-that-extends-native-html-elements/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.