DEV Community

Cover image for React Tips: Extends Props HTML Element
Kevin Toshihiro Uehara
Kevin Toshihiro Uehara

Posted on

React Tips: Extends Props HTML Element

Hi there! How have you been? How are you doing?
It's great to see you, again!

In this small article, I want to show you a tip of React with Typescript. If you are young or starting with React, propabably you already write some code like this:

interface MyCustomButtonProps {
  label: string;
  onClick?: (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void;
  isDark: boolean;
}

export const MyCustomButton = ({ label, onClick, isDark }: MyCustomButtonProps) => {
  return (
    <button className={isDark ? 'bg-black' : 'bg-white'} onClick={onClick}>
      {label}
    </button>
  );
};
Enter fullscreen mode Exit fullscreen mode

I'm creating a custom button to apply some rule logics or reuse this simple component.
But, if you see I'm using the label and onClick events, which is default props of a button element.

Michael Scott Gif Sad

How we can make this component more cleaner? Simple!
Just use the extends on your Props definition!

interface MyCustomButtonProps extends HTMLProps<HTMLButtonElement> {
  isDark: boolean;
}
Enter fullscreen mode Exit fullscreen mode

Now we can use the same props wihout redeclare the props of element itself:

interface MyCustomButtonProps extends HTMLProps<HTMLButtonElement> {
  isDark: boolean;
}

export const MyCustomButton = ({ label, onClick, isDark }: MyCustomButtonProps) => {
  return (
    <button className={isDark ? 'bg-black' : 'bg-white'} onClick={onClick}>
      {label}
    </button>
  );
};
Enter fullscreen mode Exit fullscreen mode

Simple, insn't it?

Let's see another example! Imagine that you have a custom input element:

interface MyCustomButtonProps {
  isDark: boolean;
  placeholder?: string;
  onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
  type: string;
  id?: string;
  name?: string;
}

export const MyCustomInput = ({ placeholder, onChange, isDark, name, id, type }: MyCustomButtonProps) => {
  return (
    <input
      className={isDark ? 'bg-black' : 'bg-white'}
      type={type}
      name={name}
      id={id}
      placeholder={placeholder}
      onChange={(e) => onChange}
    />
  );
};
Enter fullscreen mode Exit fullscreen mode

It's a big one! With a lot of props!
But we can simplify using, again, the extends HTMLProps passing the generic HTMLInputProps...

interface MyCustomInputProps extends HTMLProps<HTMLInputElement> {
  isDark: boolean;
}
Enter fullscreen mode Exit fullscreen mode

And let's see the entire component:

interface MyCustomInputProps extends HTMLProps<HTMLInputElement> {
  isDark: boolean;
}

export const MyCustomInput = ({ placeholder, onChange, isDark, name, id, type }: MyCustomInputProps) => {
  return (
    <input
      className={isDark ? 'bg-black' : 'bg-white'}
      type={type}
      name={name}
      id={id}
      placeholder={placeholder}
      onChange={(e) => onChange}
    />
  );
};
Enter fullscreen mode Exit fullscreen mode

More cleaner? Yep!
We are just using the props of element default itself. And adding just the props that is for our custom element.

Helpful? How I said, this is a small article, but with the principles of SOLID and tip of Typescript inference on React.

Thank you so much!
Stay well, always!

Contacts:

Image of Datadog

The Essential Toolkit for Front-end Developers

Take a user-centric approach to front-end monitoring that evolves alongside increasingly complex frameworks and single-page applications.

Get The Kit

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay