Home > Blockchain >  In a React TS component, how do I pass optional props not defined in the interface?
In a React TS component, how do I pass optional props not defined in the interface?

Time:08-30

I have the following TS React component (MyButton.tsx):

import React from 'react'

interface MyButtonProps {
  children: JSX.Element | JSX.Element[],
  className?: string,
  variant?: 'big-button' | 'medium-button' | 'small-button'
}

const MyButton = ({
  children,
  className,
  variant
}: MyButtonProps) => {
  let baseClassName: string = 'my-button'
  if (variant != null) {
    baseClassName  = ' '   variant
  }

  return (
    <button
      className={baseClassName   ' '   className}
    >
      {children}
    </button>
  )
}

export default MyButton

It's a fairly simple component to understand. I can use it in the following way:

<MyButton variant='big-button'>Click Here</MyButton>

It works fine. However, ideally I would like to pass in props to this component that are not defined in the Interface for the MyButtonProps. For example, I would like to be able to do something like the following:

<MyButton variant='small-button' type="reset" disabled>Reset Form</MyButton>

The type and disabled props are normal HTML attributes, but TS throws an error at me because I have not defined them in the Interface. How can I solve this? I remember seeing the ... operator for a use case similar to this, but can't find it anymore. Any help is greatly appreciated!

CodePudding user response:

Try this:

interface MyButtonProps extends React.HTMLProps<HTMLButtonElement> {
  children: JSX.Element | JSX.Element[],
  className?: string,
  variant?: 'big-button' | 'medium-button' | 'small-button'
}
Try this:

 const MyButton = (
  children: JSX.Element | JSX.Element[],
  className?: string,
  variant?: 'big-button' | 'medium-button' | 'small-button',
  ...others: any[]
 )
const MyButton = ({
  children,
  className,
  variant,
  ...props
}: MyButtonProps) => {
  let baseClassName: string = 'my-button'
  if (variant != null) {
    baseClassName  = ' '   variant
  }

  return (
    <button
      className={baseClassName   ' '   className}
      { ...props }
    >
      {children}
    </button>
  )
}

CodePudding user response:

Try this:

 const MyButton = (
  children: JSX.Element | JSX.Element[],
  className?: string,
  variant?: 'big-button' | 'medium-button' | 'small-button',
  ...others: any[]
 )

So this should work:

 const MyButton = (
  children: JSX.Element | JSX.Element[],
  className?: string,
  variant?: 'big-button' | 'medium-button' | 'small-button',
  ...others: any[]
 ) => {
  let baseClassName: string = 'my-button'
  if (variant != null) {
    baseClassName  = ' '   variant
  }

  return (
    <button {...others}
      className={baseClassName   ' '   className}
    >
      {children}
    </button>
  )
}

export default MyButton

Now you can use those extra props by simply spreading them in jsx element like this <button {...others}/>.

Example:

<MyButton className="blah" disabled/>

The above disabled will be applied to <button/> as follows:

<button disabled/>
  • Related