skip to Main Content

I have a component that extends a sidebar component and accepts a footer component:

interface SidebarWithFooterProps extends SidebarProps {
    footerComponent: React.ReactNode;
}


export const SidebarWithFooter: React.FC<PropsWithChildren<SidebarWithFooterProps>> = ({
    footerComponent,
    className,
    mobile,
    ...props
}) => (
    <div className={classes.root}>
        <Sidebar className={clsx(classes.content, className)} mobile={mobile} {...props} />
        <div className={classes.footer}>{footerComponent}</div>
    </div>
);

I need to add another prop ‘footerComponentProps’, that allows us to provide props to pass to the footerComponent.

My problem is how to type that? How can I get the props for the provided footerComponent? I’ve tried with a generic:

interface SidebarWithFooterProps<T extends React.ReactElement> extends SidebarProps {
    footerComponent: T;
    footerComponentProps?: React.ComponentProps<T>;
}

export const SidebarWithFooter: React.FC<PropsWithChildren<SidebarWithFooterProps<React.ReactElement>>> = ({…

but this results in an error on React.ComponentProps<T>:

Type 'T' does not satisfy the constraint 'JSXElementConstructor<any> | keyof IntrinsicElements'

(and then SidebarWithFooterProps<React.ReactElement> feels redundant, but needs an argument)

I’m definitely getting the generic wrong and I’m not sure what <T extends React.ReactElement> should be?

2

Answers


  1. Here’s an example of your component and its props:

    interface SidebarWithFooterProps<T extends React.ElementType> extends SidebarProps {
        footerComponent: React.ReactElement<T>;
        footerComponentProps?: React.ComponentProps<T>;
    }
    
    export const SidebarWithFooter = <T extends React.ElementType>({
        footerComponent: FooterComponent,
        footerComponentProps,
        className,
        mobile,
        ...props
    }: PropsWithChildren<SidebarWithFooterProps<T>>) => (
        <div className={classes.root}>
            <Sidebar className={clsx(classes.content, className)} mobile={mobile} {...props} />
            <div className={classes.footer}>
                <FooterComponent {...footerComponentProps} />
            </div>
        </div>
    );
    

    Usage Example:

    // Assuming you have a FooterComponent like this:
    const MyFooterComponent: React.FC<{ message: string }> = ({ message }) => (
        <div>{message}</div>
    );
    
    // Usage of SidebarWithFooter
    <SidebarWithFooter
        sidebarProps={/* ... */}
        footerComponent={<MyFooterComponent message="Hello" />}
        footerComponentProps={{ message: "World" }}
        // ...
    />
    
    Login or Signup to reply.
  2. You can make use of the generic type P for the props instead

    interface SidebarWithFooterProps<P> extends SidebarProps {
      footerComponent: React.ReactElement<P>;
      footerComponentProps?: P;
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search