Here I am trying to render the contents of Accordion
through a list array passing down the props to a component. I kind of understand where the issue is but I don't know how else I can call the component and pass the props. Below is my code.
Code of the parent component
const Sandbox = () => {
let summaryContents: any[] = [
{
Title: "Construction costs",
TotalPrice: "$25000",
Subcontents: [
{
Subtitle: "Sanitation",
SubtitlePrice: "$5000",
},
{
Subtitle: "PoolLights",
SubtitlePrice: "$5000",
},
{
Subtitle: "PoolCleaner",
SubtitlePrice: "$15000",
},
],
},
{
Title: "Pool interior costs",
TotalPrice: "$20000",
Subcontents: [
{
Subtitle: "Title1",
SubtitlePrice: "$5000",
},
{
Subtitle: "Title2",
SubtitlePrice: "$10000",
},
{
Subtitle: "Title3",
SubtitlePrice: "$5000",
},
],
},
];
let summaryContentsList: any[] = [];
summaryContents.forEach((item: any, index: number) => {
summaryContentsList.push(
<QuoteSummary
Title={item.Title}
TotalPrice={item.TotalPrice}
Subtitle={item.Subcontents.Subtitle}
SubtitlePrice={item.Subcontents.SubtitlePrice}
/>
);
});
return (
<>
{summaryContentsList}
</>
);
};
Code for the child component
const QuoteSummary: FC<QuoteSummaryProps> = (props: QuoteSummaryProps) => {
const classes = useStyles();
return (
<QuoteCard>
<Typography variant="h1" sx={{ paddingBottom: 2 }}>
Quote Summary
</Typography>
<DialogCloseButton onClose={clicked} />
<Accordion
className={classes.accordion}
sx={{
paddingTop: 0,
}}
>
<AccordionSummary
expandIcon={<ExpandMoreIcon />}
aria-controls="panel1a-content"
id="panel1a-header"
>
<Typography variant="h3">{props.Title}</Typography>
<Typography variant="h3" sx={{ paddingLeft: 10 }}>
{props.TotalPrice}
</Typography>
</AccordionSummary>
<AccordionDetails>
<Typography>{props.Subtitle}</Typography>
<Typography>{props.SubtitlePrice}</Typography>
</AccordionDetails>
</Accordion>
</QuoteCard>
);
};
This is how it looks where as I wanted to render the Title only once and accordion contents below. What would be the approach I will have to follow
CodePudding user response:
You can put the QuoteCard
outside and only place Accordion
item in the child component:
const QuoteSummary: FC<QuoteSummaryProps> = (props: QuoteSummaryProps) => {
return (
<Accordion>
{...}
</Accordion>
);
};
<QuoteCard>
<Typography variant="h6" sx={{ paddingBottom: 2 }}>
Quote Summary
</Typography>
<DialogCloseButton onClose={() => {}} />
{summaryContents.map((item) => (
<QuoteSummary
Title={item.Title}
TotalPrice={item.TotalPrice}
Subtitle={item.Subcontents.Subtitle}
SubtitlePrice={item.Subcontents.SubtitlePrice}
/>
))}
</QuoteCard>
EDIT: Another approach is to render the title conditionally in the child component based on the props provided from the parent:
const QuoteSummary: FC<QuoteSummaryProps> = (props: QuoteSummaryProps) => {
return (
<QuoteCard>
{props.displayTitle && (
<Typography variant="h6" sx={{ paddingBottom: 2 }}>
Quote Summary
</Typography>
)}
<DialogCloseButton onClose={() => {}} />
<Accordion>
{...}
</Accordion>
</QuoteCard>
);
};
<>
{summaryContents.map((item, i) => (
<QuoteSummary
displayTitle={i === 0}
Title={item.Title}
TotalPrice={item.TotalPrice}
Subtitle={item.Subcontents.Subtitle}
SubtitlePrice={item.Subcontents.SubtitlePrice}
/>
))}
</>
CodePudding user response:
You can create a render function for array items and use them like this:
const Sandbox = () => {
const summaryContents: any[] = [
{
Title: "Construction costs",
TotalPrice: "$25000",
Subcontents: [{
Subtitle: "Sanitation",
SubtitlePrice: "$5000",
},
{
Subtitle: "PoolLights",
SubtitlePrice: "$5000",
},
{
Subtitle: "PoolCleaner",
SubtitlePrice: "$15000",
},
],
},
{
Title: "Pool interior costs",
TotalPrice: "$20000",
Subcontents: [{
Subtitle: "Title1",
SubtitlePrice: "$5000",
},
{
Subtitle: "Title2",
SubtitlePrice: "$10000",
},
{
Subtitle: "Title3",
SubtitlePrice: "$5000",
},
],
},
];
const renderContent = (item: any) => (
<QuoteSummary
Title={item.Title}
TotalPrice={item.TotalPrice}
Subtitle={item.Subcontents.Subtitle}
SubtitlePrice={item.Subcontents.SubtitlePrice}
/>
);
return (
<>
{summaryContents.map(renderContent)}
</>
);
};