Issue
Using React with TypeScript, there are several ways to define the type of children, like setting it to JSX.Element or React.ReactChild or extending PropsWithChildren. But doing so, is it possible to further limit which particular element that React child can be?
function ListItem() {
return (
<li>A list item<li>
);
}
//--------------------
interface ListProps {
children: React.ReactChild | React.ReactChild[]
}
function List(props: ListProps) {
return (
<ul>
{props.children} // what if I only want to allow elements of type ListItem here?
</ul>
);
}
Given the above scenario, can List be set up in such a way that it only allows children of type ListItem? Something akin to the following (invalid) code:
interface ListProps {
children: React.ReactChild<ListItem> | React.ReactChild<ListItem>[]
}
Solution
You can't constrain react children like this.
Any react functional component is just a function that has a specific props type and returns JSX.Element. This means that if you render the component before you pass it a child, then react has no idea what generated that JSX at all, and just passes it along.
And problem is that you render the component with the <MyComponent> syntax. So after that point, it's just a generic tree of JSX nodes.
This sounds a little like an XY problem, however. Typically if you need this, there's a better way to design your api.
Instead, you could make and items prop on List which takes an array of objects that will get passed as props to ListItem inside the List component.
For example:
function ListItem({ children }: { children: React.ReactNode }) {
return (
<li>{children}</li>
);
}
function List(props: { items: string[] }) {
return (
<ul>
{props.items.map((item) => <ListItem>{item}</ListItem> )}
</ul>
);
}
const good = <List items={['a', 'b', 'c']} />
In this example, you're just typing props, and List knows how to generate its own children.
Answered By - Alex Wayne
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.