#reactjs #typescript
Вопрос:
У меня есть PropertyCardList
компонент, который принимает некоторые props
. Я хочу передать только имя компонента от родителя, и список должен автоматически отображать его.
PropertyCardList.tsx
import React from "react";
import { Grid, GridProps, GridSpacing } from "@material-ui/core";
import { NamedExoticComponent } from "react";
import { LargePropertyInfo, SmallPropertyInfo } from "../../@types/Property/Property";
import { SmallPropertyCardProps } from "../PropertyCards/SmallPropertyCard/SmallPropertyCard";
import { LargePropertyCardProps } from "../PropertyCards/LargePropertyCard/LargePropertyCard";
interface Props
{
gridSpacing?: GridSpacing;
gridItemProps?: GridProps;
loading?: boolean;
skeletonsCount?: number;
properties: SmallPropertyInfo[] | LargePropertyInfo[];
cardComponent: NamedExoticComponent <SmallPropertyCardProps> | NamedExoticComponent <LargePropertyCardProps>;
}
const PropertyCardList: React.FC <Props> = props =>
{
if (props.loading)
{
return (
<Grid container spacing={props.gridSpacing}>
{new Array(props.skeletonsCount).fill(null).map((_, index) => (
<Grid
item
key={index}
{...props.gridItemProps}
>
<props.cardComponent
property={{}} // I have to typecast it using "as" but what should be the value?
loading={true}
/>
</Grid>
))}
</Grid>
)
}
return (
<Grid container spacing={props.gridSpacing}>
{props.properties.map((property) => (
<Grid
item
key={property.id}
{...props.gridItemProps}
>
<props.cardComponent
property={property} // I get error here saying that subType, ownership missing in SmallPropertyInfo. It makes sense but this needs to be dynamic as well
/>
</Grid>
))}
</Grid>
);
}
PropertyCardList.defaultProps = {
skeletonsCount: 3,
}
export default React.memo(PropertyCardList);
Интерфейсы
export interface PropertyBase
{
id: string;
images: string[];
beds: number;
baths: number;
areaSize: number;
price: PropertyPrice;
address: ObjectWithTranslation;
}
export interface SmallPropertyInfo extends PropertyBase
{
purpose: PropertyPurpose;
}
export interface LargePropertyInfo extends SmallPropertyInfo
{
subType: PropertySubType;
ownership: PropertyOwnership;
installment: Omit <PropertyPrice, "type">;
}
Ниже показано, как я использую компонент списка:
<PropertyCardList
cardComponent={isMobile ? SmallPropertyCard : LargePropertyCard}
properties={properties.data}
gridSpacing={2}
gridItemProps={{
lg: 6,
xs: 12
}}
loading={loading}
skeletonsCount={5}
/>
Является ли это правильным подходом к созданию общего компонента списка или мне следует создавать отдельные компоненты списка для каждого отдельного типа? (Это будет дублировать много кода)
Ответ №1:
В react можно использовать условную визуализацию, и действительно полезно удалить избыточную реализацию кодирования.
Вы можете использовать его в качестве переменной в теле функции следующим образом.
const cardComponent= isMobile ? SmallPropertyCard : LargePropertyCard
А затем используйте его для перехода в дочерний компонент следующим образом.
<PropertyCardList
cardComponent={cardComponent}
properties={properties.data}
gridSpacing={2}
gridItemProps={{
lg: 6,
xs: 12
}}
loading={loading}
skeletonsCount={5}
/>
То, как вы его используете, тоже правильно.
Комментарии:
1. Моя ошибка связана с
PropertyCardList
компонентом из-за конфликтов типов (я написал комментарий). То, о чем вы упомянули, уже работает нормально.