Home  >  Q&A  >  body text

Is there a seamless way to combine custom and native props in a REACT TS component wrapper?

I have several components that extend the native functionality of inputs, buttons, forms, etc., but I find it tedious to have to include every event handler and prop when the team needs it.

I tried simply making the component prop type extend the native prop type and then using object propagation to automatically apply all the native props. The next problem is that custom props are not supported and should not be applied to native elements.

To solve this problem, the only solution I found was to copy the name of each custom prop in the component parameters like this: {customProp1, customProp2, ...nativeProps}. However, this solution, while much better than having to add all native props, forces me to copy all the props and I lose the props. I like the prefix used to distinguish props from local variables.

Is there a clever way to filter out native props from custom props?

Example of what I want to achieve:

import React from 'react'

type Props = {
    color: string,
}

const Button = ({...props}: Props, {...nativeProps} : React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>) => {
  return (
    <button {...nativeProps} style={{backgroundColor: props.color}}  />
  )
}

export default Button

My current best solution involves copying each prop name and using the spread operator on the remaining props.

import React from 'react'

type CustomProps = {
    color: string,
    label: React.ReactNode,
    name: string,
}

type Props = CustomProps & Omit<React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, keyof CustomProps>;

const Button = ({color, label, ...props}: Props) => {

  return (
    <>
        {label}
        <button {...props} style={{backgroundColor: color}} />
    </>
  )
}

export default Button

P粉186897465P粉186897465225 days ago416

reply all(1)I'll reply

  • P粉826283529

    P粉8262835292024-03-31 16:20:38

    Have you tried using interface with extends?

    import React from 'react';
    
    interface IButtonProps
      extends React.DetailedHTMLProps<
        React.ButtonHTMLAttributes,
        HTMLButtonElement
      > {
      color: string;
    }
    
    const Button = ({ color, ...props }: IButtonProps) => {
      return 

    Otherwise, you can nest native button props:

    import React from "react";
    
    interface IButtonProps {
      color: string;
      buttonProps?: React.DetailedHTMLProps<
        React.ButtonHTMLAttributes,
        HTMLButtonElement
      >;
    }
    
    const Button = ({ buttonProps, ...props }: IButtonProps) => {
      return 

    reply
    0
  • Cancelreply