How to pass all props to a component in React?

87 Views Asked by At

I designed the below button using TailwindCSS with onClick event.

<button className="border bg-purple-600 rounded-lg text-white px-2 py-1 mb-4" onClick={handleClick}>
  Add Item
</button>

Now I tried creating a React component for this button. I want to use this component everywhere and sometimes it will have onClick prop, sometimes onMouseDown, etc. So I am trying to set whatever props are passed to my component on the button element inside the component. I came up with below.

function Button({
  children,
  ...props
}: {
  children: React.ReactNode;
  props?: any;
}) {
  return (
    <button
      className="border bg-purple-600 rounded-lg text-white px-2 py-1 mb-4"
      {...props}
    >
      {children}
    </button>
  );
}

I did not know what to set the type of props so I've set it to any for now. This code does not show any errors.

But when I try to use the component as below, it says: Type '{ children: string; onClick: () => void; }' is not assignable to type 'IntrinsicAttributes & { children: ReactNode; props?: any; }'

<Button onClick={handleClick}>
   Add Item
</Button>

How can I get this working?

1

There are 1 best solutions below

0
Phil On BEST ANSWER
{
  children: React.ReactNode;
  props?: any; //  this is incorrect
}

Your component does't accept a props property. Instead, you're spreading the rest of the props. This means the above type definition won't match what you're passing to it.

Given you're just creating a button wrapper, you can use its default attributes (which already includes children).

import type { ButtonHTMLAttributes } from "react";

function Button({
  children,
  ...props
}: ButtonHTMLAttributes<HTMLButtonElement>) {
  // ...
}

You might also want to prevent consumers passing in a className which would overwrite your own classes.

You could either just add yours after...

<button
  {...props}
  className="border bg-purple-600 rounded-lg text-white px-2 py-1 mb-4"
>
  {children}
</button>

or expressly forbid it in the prop type

type ButtonProps = Omit<ButtonHTMLAttributes<HTMLButtonElement>, "className">;

function Button({
  children,
  ...props
}: ButtonProps) {
  return (
    <button
      className="border bg-purple-600 rounded-lg text-white px-2 py-1 mb-4"
      {...props}
    >
      {children}
    </button>
  );
}