DEV Community

loading...
Cover image for How to use TypeScript generics to create data-agnostic React components

How to use TypeScript generics to create data-agnostic React components

courseprobe profile image Course Probe ・2 min read
interface Props<T> {
  children: (item: T) => React.ReactNode
  dir: 'horizontal' | 'vertical'
  dividers?: boolean
  items: T[]
  windowing?: boolean
}

interface IdObj {
  id: string | number
}

const List = <T extends IdObj>({
  children,
  dir,
  dividers,
  items,
  windowing,
}: Props<T>) => {
  const className = genClassName({ dir, dividers })
  const visibleItems = useWindowing(items, windowing)

  return (
    <div className={className}>
      {visibleItems.map((item) => (
        <div key={item.id} className="item">
          {children(item)}
        </div>
      ))}
    </div>
  )
}

Enter fullscreen mode Exit fullscreen mode

Setting up generic props creates a better developer experience:

const JSFrameworks = () => {
  // 👋🏾 hand-wavy custom hook that returns an array of JS frameworks
  const frameworks = useFrameworks('js')

  return (
    <List items={frameworks} dir="vertical">
      {(framework) => (
        <dl>
          <dt>Name</dt>
          <dd>{framework.name}</dd>

          <dt>Created</dt>
          <dd>{framework.since}</dd>

          <dt>Author</dt>
          <dd>{framework.author}</dd>
        </dl>
      )}
    </List>
  )
}
Enter fullscreen mode Exit fullscreen mode

The caller doesn't have to use a type assertion in the render prop to coerce the framework argument to the correct type. It's automatically kept in sync with the type of the frameworks array passed to the items prop. And because the types are all inferred, we never have to explicitly define the type of items or children.

Full blog post: https://www.benmvp.com/blog/generic-react-components-typescript/?utm_source=reddit&utm_medium=social&utm_campaign=init-share

Additional resources:

Get the book: React Documentation


Other Dev posts:

Discussion (1)

pic
Editor guide
Collapse
alfredosalzillo profile image
Alfredo Salzillo

Please add the typescript tag to the code blocks for syntax highlights.