Sossenbinder
Sossenbinder

Reputation: 5302

How to create a generic React.FC?

I was wondering whether there is an easy way of creating a generic React.FC.

My use case is the following: I want to create a generic table component for a page I'm working on, and I'd really like to have generic support in order to have type safety on possible click callback etc.

I already tried out a few things. Here are the props I'd like to have, first of all:

type Props<T> = {
    entries: Array<T>;
}

So, here is my first attempt:

export const DataGridBody = <T extends any>(props: Props<T>) => {

    return (
        <>
            {props.entries}
        </>
    );
}

What's working well, is that implementers can just use e.g. <DataGridBody<MyType> .... />. What's bad, is that it's not a React.FC but a JSX.Element, which apparently leads to missing autocompletion of props etc.

Okay, I tried and read up a bit more and here is my second attempt:

export const createDataGridBody = <T extends any>(): React.FC<Props<T>> => {
    return (props: Props<T>) => {
        return (
            <>
                ...
            </>
        )
    }
}

const PreTypedBody = createDataGridBody<number>();

<PreTypedBody 
    entries={[0, 1]}/>

Awesome! This works! And it is a React.FC with autocompletion. However, it's fairly clunky to use.

So, to sum it up, I was wondering if there is a good approach which kind of combines both of these?

Upvotes: 3

Views: 2914

Answers (1)

Siraj Alam
Siraj Alam

Reputation: 10025

It seems for me worth good to go.

Just picked the return type pf the FC and prop types from React and added manually, as passing a generic reverse to FC is not quite possible.

import React, {ReactElement, PropsWithChildren} from 'react';

interface NameProps<T> { 
  entries: T[];
}

const Name = <T>(props: PropsWithChildren<NameProps<T>>):ReactElement<any, any> | null => {
  return (
      <>
         ...
      </>
  );
}

Playground Link

Upvotes: 5

Related Questions