Open posita opened 4 years ago
I agree that circular propTypes are needed for a tree-like structure that allows circularity, but that specific need is indeed exceedingly rare.
You'd handle this by using a custom propType to wrap the recursion, rather than actually using recursion.
To clarify, what I'm pointing out by filing this issue is that no clear guidance exists to address this pattern. I've clearly gotten it wrong here, but that's largely because I've been feeling around in the dark absent such guidance.
You'd handle this by using a custom propType to wrap the recursion, rather than actually using recursion.
☝️ Thanks, but I don't understand what that means or whether it differs from your prior recommendation on #246. Can you point to a clear example?
Right now, I've constructed the following work-around:
type LeafComponentT = InferProps<typeof LeafComponent.propTypes>
function LeafComponent({ id, name }: LeafComponentT) {
return (
<span>{name} ({id})</span>
)
}
LeafComponent.propTypes = {
id: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
}
interface RootComponentT {
children: NodeComponentT[],
}
function RootComponent({ children }: RootComponentT) {
if (children
&& children.length > 0) {
return (
<ul>
{children.map((child, _) => (
<NodeComponent {...child} />
))}
</ul>
)
} else {
return null
}
}
RootComponent.propTypes = {
children: PropTypes.array.isRequired,
}
type NodeComponentT = RootComponentT & {
leaf: InferProps<typeof LeafComponent.propTypes>,
}
function NodeComponent({ leaf, children }: NodeComponentT) {
return (
<li>
<LeafComponent key={leaf.id} {...leaf} />
<RootComponent children={children} />
</li>
)
}
NodeComponent.propTypes = {
leaf: PropTypes.shape(LeafComponent.propTypes).isRequired,
children: PropTypes.array.isRequired,
}
I call this a work-around because there is no runtime type checking of the elements of children
.
This comment claims this use case is pretty rare, but I'm either ignorant of the alternatives, or I'm not convinced. Anywhere one wants to have a tree-like component structure, one potentially butts up against this limitation. Consider a structure involving
Node
s andLeaf
s as follows:So far, a
Node
is merely a list ofLeaf
s. Now let's say we want to augment ourNode
to contain zero or more entries, each of which may either be aNode
orLeaf
. How is this done? This won't work:You'll get a circular reference type error. So how should one handle this case in the real world? I can find near zero documentation on how to do this, either here or via the React docs. Any guidance would be appreciated.