Suppose you have a Card
component that takes content for the header, body and footer. One way to design it would be for consumers to use it like this:
<Card
header="foo"
body="bar"
footer="baz"
/>
But I often prefer something like this:
<Card>
<CardHeader>foo</CardHeader>
<CardBody>bar</CardBody>
<CardFooter>baz</CardFooter>
</Card>
To get the latter, I’m currently doing something like this:
const cardHeader = children.find(
(child) => child && child.type && child.type.name === "CardHeader",
);
But I wonder if there is a more idiomatic way of doing it.
2
Answers
From what I understand you cannot specify children, you can specify props.
I would probably end up doing something like this:
Edit: Thanks for the downvote I hope you find what you’re looking for.
A general term you might look for is "slots", especially when used in reference to Vue’s slot feature or the Web Components
<slot>
definition in HTML. As of this writing, there is not an official idiomatic equivalent in React, but React RFC #223 ("Slots") proposes an extension in the future. That GitHub thread also describes some of the popular alternatives and the concerns in building this feature directly into React.For lack of an official "slot" solution, the most idiomatic built-in way to represent this in React is as you suggested:
You might also consult Sandro Roth’s article "Building Component Slots in React", which helpfully linked the RFC above. In particular, it describes the type safety benefits and concerns of the above pattern in comparison to "compound components"—a term which does not appear in official React docs but describes the pattern of nested tightly-coupled components that you depict in your question. This pattern does appear in libraries like
react-bootstrap
(e.g. hasChildOfType and its consumption) but the pattern is just that—a common design pattern that is not described or endorsed in the React docs.