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:

Top comments (0)