【问题标题】:Dynamically render string as html component in TypeScript在 TypeScript 中将字符串动态呈现为 html 组件
【发布时间】:2022-12-01 03:55:30
【问题描述】:

我如何输入接受ComponentTypestring 的道具?

假设有以下代码。

interface MyComponentProps {
    Component: React.ComponentType
}
const MyComponent: React.FC<PropsWithChildren<MyComponentProps>> = ({Component}) => {
    return <Component>{children}</Component>
}
<MyComponent
    Component="span"
/>

在 TS 中尝试此操作会出现以下错误。

类型“字符串”不可分配给类型“ComponentType<{}> |不明确的'。

如何使用 JSX 动态渲染原生 html 标签?

【问题讨论】:

    标签: reactjs typescript


    【解决方案1】:

    你不能用 JSX 真正做到这一点。

    然而,JSX 是 React.createElement 的语法糖。

    // these are basically the same.
    const jsxEl = <a href="/">Home</a>
    const manualEl = React.createElement('a', { href: '/' }, 'Home')
    

    这意味着你可以做类似的事情:

    interface MyComponentProps {
        component: "span" | "div"
        children: React.ReactNode
    }
    
    function MyComponent({component, children}: MyComponentProps) {
        return React.createElement(component, null, children)
        //                         ^tag.      ^props   ^children 
    }
    
    // test
    <MyComponent component="span">
      span content here
    </MyComponent>
    

    注意:我还在这里清理了你的代码。 React.FC 在现代 React 中并不真正推荐,PropsWithChildren 很容易明确。

    See Playground

    【讨论】:

      【解决方案2】:

      就反应和javascript而言,您的代码是正确的。这里的问题是类型。字符串 "span" 不是 ComponentTypeComponent 所需的类型是 React.ElementType。如果您查看 ElementType 的定义,它包含所有内部 jsx 元素或组件类型。

      您可以通过呈现 &lt;span&gt;&lt;/span&gt; 并将鼠标悬停在或单击 span 关键字来自行得出此结论。你会看到类型是JSX.IntrinsicElements.span。如果你点击进去,你可以看到 IntrinsicElements 包含了所有的 html 元素。我进行了搜索以查看使用该类型的位置,这使我找到了React.ElementType

      更新代码:

      interface MyComponentProps {
          Component: React.ElementType
      }
      const MyComponent: React.FC<PropsWithChildren<MyComponentProps>> = ({Component}) => {
          return <Component>{children}</Component>
      }
      <MyComponent
          Component="span"
      />
      

      旁注:React.FC 可能不再是最佳方法。相反,直接为道具分配一个类型似乎更可取:

      const MyComponent = ({Component}: PropsWithChildren<MyComponentProps>) => {
          return <Component>{children}</Component>
      }
      

      如果您有兴趣,请在此处了解更多信息:https://github.com/facebook/create-react-app/pull/8177

      【讨论】:

        猜你喜欢
        • 2021-08-17
        • 2020-06-11
        • 2022-08-24
        • 2016-07-28
        • 2015-02-01
        • 1970-01-01
        • 2022-01-25
        相关资源
        最近更新 更多