I was thinking about how to create a generic component that handles different shapes of data to render a list of items. A simplified example of this component looks as following:
const OverviewItem = ({ title, subtitle }: { title: string, subtitle: string }) => {
return (
<div>
<p> {title} </p>
<p> {subtitle} </p>
</div>
)
}
export const Overview = <T,>({ items }: { items: T[] }) => {
return (
<section>
items.map((item) => (<OverviewItem title={...} subtitle={...} />))
</section>
)
}
The idea is that the Overview
component receives an array of items which will then be rendered. However, because we do not know what properties an item
will have (because it’s generic), we can not directly pass an item’s property as subtitle or title to the OverviewItem
component.
I thought about doing this using a render prop, but I want to limit the usage of the component that gets returned from the map function to the OverviewItem
component. I also would like to avoid passing an item’s property paths for a title and/or subtitle. However, this is not very ergonomic.
I have also tried to allow a transform prop (function) which the user can pass as a property to the Overview component. This function has to return an object with the title and subtitle properties. These will then be spread on the OverviewItem when we map over the items, like so: items.map((item) => <OverviewItem {...transform(item)} />)
.
This way I always have type safety and can specify which properties should be the title and subtitle. I also do not have to iterate and transform the entire array prior to passing it to the Overview component.
However, I am not entirely satisfied with the things I have tried so far and I am wondering what the best way to approach this would be?
I’d love to hear your suggestions!
frosan is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.