【问题标题】:How to pass node as prop to component in React?如何将节点作为道具传递给 React 中的组件?
【发布时间】:2020-07-30 05:41:22
【问题描述】:

试图将逻辑与设计分开。

以下是我要解决的问题的简化版本。

import React, { ReactNode } from "react"

interface ChildProps {
  id: string
}

const Child = function (props: ChildProps) {
  return <div id={props.id} />
}

interface ParentProps {
  id: string
  node: ReactNode
}

const Parent = function (props: ParentProps) {
  return <props.node id={props.id} /> // Throws "JSX element type 'props.node' does not have any construct or call signatures.ts(2604)" error
}

【问题讨论】:

  • 你希望如何传递node?是传入像 node={MyComponent} 这样的功能组件还是像 node={&lt;div&gt;foo&lt;/div&gt;} 这样渲染 JSX?
  • @AlexWayne node={MyComponent} 忘了提到我需要能够在功能块内设置该节点的道具。

标签: reactjs typescript


【解决方案1】:

ReactNode 是一种用于渲染 JSX 的类型,因此您希望将您的 prop 键入为功能组件,

interface TestProps {
  node: React.FC
}

然后应该像你期望的那样工作:Playground


将 JSX 组件呈现为 title-case JSX 标记也是一个很好的最佳实践。这在更复杂的组件中更容易阅读。这使得它类似于:

const Test = function (props: TestProps) {
    const Node = props.node
    return <Node />
}

如果您要接受的组件采用id 属性,您可以在node 的props 类型中指定它。

interface TestProps {
    node: React.FC<{ id: number }>
}

现在您可以像分配任何其他道具一样分配道具:

const Test = function(props: TestProps) {
    const Node = props.node
    return <Node id={123} />
}

Playground


最后,您可以疯狂地使用泛型并推断 node 的道具类型,并让包装器组件接受节点接受的所有道具,无论它们是什么。

interface TestProps<P> {
    node: React.FC<P>
    nodeProps: P
}

const Test = function<P>({ node: Node, nodeProps }: TestProps<P>) {
    return <Node {...nodeProps} />
}

Playground

这在学术上很有趣,但与仅通过渲染的 JSX 进行渲染并没有太大区别。

【讨论】:

  • 谢谢亚历克斯,我们接近了......你将如何处理分配id={props.id}?目前ChildProps没有被推断出来。
  • 如果你传入 props,那么你可能想要传入渲染的 JSX。确定不想改为node={&lt;MyComponent id={id} /&gt;}
  • 也许我没有编写正确的 React 代码,但目前,id 不为 Child 提前知晓,其设计更改基于 Parent 定义的 props。
  • 尝试使用 React.FunctionComponent&lt;any&gt; 并看起来很有希望,但如果 node 的类型以某种方式推断出来,我会更喜欢。
  • 增加了一个使用泛型的选项,因为泛型很有趣。并感谢该链接的提示。反正那里没有太多公开的:)
猜你喜欢
  • 2018-08-01
  • 2021-12-21
  • 2017-09-06
  • 1970-01-01
  • 2020-12-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-04
相关资源
最近更新 更多