将React与TypeScript一起使用时,有几种方法可以定义children
的类型,比如将其设置为JSX.Element
或React.ReactChild
,或者扩展PropsWithChildren
。但是这样做是否可以进一步限制React子元素可以是哪个特定元素?
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>
);
}
在上面的场景中,List
是否可以设置为只允许ListItem
类型的子级?类似于以下(无效)代码:
interface ListProps {
children: React.ReactChild<ListItem> | React.ReactChild<ListItem>[]
}
3条答案
按热度按时间e5nszbig1#
你不能这样约束孩子的React。
任何react函数组件都只是一个具有特定props类型并返回
JSX.Element
的函数。这意味着如果在传递子组件之前 render 该组件,则react根本不知道生成JSX的是什么,只是沿着。问题是你用
<MyComponent>
语法来呈现组件,所以在这之后,它只是一个JSX节点的通用树。这听起来有点像一个XY problem,但是,如果你需要它,通常有一个更好的方法来设计你的api。
相反,您可以在
List
上创建和items
prop,List
接受一个对象数组,这些对象将作为prop传递给List
组件中的ListItem
。例如:
在本例中,您只是输入props,而
List
知道如何生成它自己的子对象。Playground
h9vpoimq2#
下面是一个基本示例,我将其用于一个包含多个步骤的“向导”。它使用一个主组件WizardSteps(复数)和一个子组件WizardStep(单数),后者具有一个“label”属性,该属性在主WizardSteps组件中呈现。使其正确工作的关键是Children.map(...)调用,该调用确保React将“children”视为一个数组。并且还允许Typescript和IDE正常工作。
svmlkihl3#
当然。您只需要使用
React.ReactElement
作为适当的泛型。编辑-我已经为您创建了一个示例CodeSandbox:
https://codesandbox.io/s/hardcore-cannon-16kjo?file=/src/App.tsx