是否可以使用react with typescript将子级限制为特定组件?

carvr3hs  于 2021-09-29  发布在  Java
关注(0)|答案(2)|浏览(333)

使用react with typescript,有几种方法可以定义 children ,喜欢设置为 JSX.ElementReact.ReactChild 或延伸 PropsWithChildren . 但这样做,是否有可能进一步限制子元素可以是哪个特定元素?

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>[]
}
qvtsj1bj

qvtsj1bj1#

你不能这样约束孩子。
任何react功能组件都只是一个具有特定道具类型并返回的函数 JSX.Element . 这意味着,如果在将组件传递给子组件之前呈现该组件,那么react根本不知道是什么生成了该jsx,而只是传递它。
问题是,使用 <MyComponent> 语法。因此,在这一点之后,它只是一个jsx节点的通用树。
然而,这听起来有点像xy问题。通常,如果您需要它,有一种更好的方法来设计您的api。
相反,你可以做和 items 支撑 List 它接受一组对象,这些对象将作为道具传递给 ListItem 内部 List 组成部分。
例如:

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']} />

在本例中,您只需键入道具 List 知道如何产生自己的孩子。
操场

bwitn5fc

bwitn5fc2#

绝对地你只需要使用 React.ReactElement 对于正确的泛型。

interface ListItemProps {
   text: string
}

interface ListProps {
   children: React.ReactElement<ListItemProps> | React.ReactElement<ListItemProps>[];
}

编辑-我为您创建了一个示例代码沙盒:
https://codesandbox.io/s/hardcore-cannon-16kjo?file=/src/app.tsx

相关问题