I am working on a project (React + TS) that accepts an “uncalled” component (in the example below, I’m using SimpleCard
), does some stuff behind the scenes (removed from the example for simplicity), and then renders the card component in a grid (using CardGrid
below).
In SimpleCardGrid
, note the three attributes in CardGrid
. CardGrid
should take in a component
. That component
(aka the card) is expected to be constructed a certain way (the same way SimpleCard
is constructed). ICardGrid
should be able to read the component
and figure out the type for items
(an array of ISimpleCardItem
, or whatever the type for the card) and componentProps
(in this case, it should expect isDataLoaded
).
However, I struggling with how to do this correctly. I can’t seem to figure out how to change ICardGrid
to make this happen (I’ve tried different variations using a generic). Please help – thank you!!!!
Here is the simplified code:
import * as React from 'react';
type IKey = { key: string };
type ISimpleCardItem = IKey & { text: string };
type IItem<T> = { item: T };
type IIsDataLoaded = { isDataLoaded: boolean };
type ISimpleCard = IItem<ISimpleCardItem> & IIsDataLoaded;
const SimpleCard = ({ item, isDataLoaded }: ISimpleCard) => {
if (!isDataLoaded) {
return <div>Loading</div>;
} else {
return <div>{item.text}</div>;
}
};
type ICardGrid = {
component: any;
items: any[];
componentProps?: any;
}
const CardGrid = ({ component: Component, items, componentProps }: ICardGrid) => {
return (
<div>
{items?.map((item) => (
<Component key={item.key} item={item} {...componentProps} />
))}
</div>
);
};
const simpleCardItems: ISimpleCardItem[] = [
{
key: 'thisOne',
text: 'Hello trees',
},
{
key: 'thatOne',
text: 'Hello sky',
},
{
key: 'theOtherOne',
text: 'Hello world',
},
];
const SimpleCardGrid = () => {
return (
<CardGrid
component={SimpleCard}
items={simpleCardItems}
componentProps={{
loading: false,
thisShouldThrowAnError: false,
}}
/>
);
};