如何将JSX元素包装在React.ReactNode变量中

huangapple go评论64阅读模式
英文:

How to wrap JSX elements in a React.ReactNode variable

问题

I understand your request. Here's the translated content without the code parts:

这段代码似乎有问题,出现了错误:JSX元素没有任何构造或调用签名

换句话说,你想要拿到 MyButton 变量并注入子元素。你可以如何实现这一点呢?

我尝试使用了 React.createElement:

{React.createElement(
  MyButton,
  {},
  <div>
    <p>子元素 1</p>
    <p>子元素 2</p>
  </div>
)}

但它不接受 React.ReactNode 作为类型。

我尝试实现的真正用例是:
我正在使用 @react-pdf/renderer 包,它有一个组件,你可以将其包装在一个按钮上,然后点击该按钮将生成 PDF。

在我的组合中,我试图通过使用两个独立的组件来实现它,一个组件将传递一个 PDF 库(在这个示例中是 react-pdf renderer)的 PDF 生成组件,另一个组件不知道使用的是哪个库。第二个组件将获取 PDF 生成组件并将其包装在一个按钮周围。

第一个组件:

import { PDFDownloadLink } from '@react-pdf/renderer';

export default function FirstComponent() {
  return (
    <SecondComponent
      {...props}
      downloadPdfElement={
        <PDFDownloadLink
          document={<MyPdfDoc pdfTimelineRows={pdfTimelineRows} />}
          fileName="pdf"
        />
      }
    />
  );
}

第二个组件只需使用 downloadPdfElement 属性并将其包装在某个按钮周围。

如果将所有代码放在一个组件中是更容易的,只需将 PDFDownloadLink 包装在按钮周围,那就可以了,但我想将其拆分为两个独立的组件。如果实现起来太复杂,也可以是一个答案。

英文:

I have a React.ReactNode variable (which can be passed as props)

export default function App() {
  const MyButton = &lt;Button size=&#39;large&#39;/&gt;
  return (
    &lt;div&gt;
      &lt;MyButton&gt;Click here&lt;/MyButton&gt;
    &lt;/div&gt;
  );
}

But this code doesn't work - I'm getting the error: JSX element does not have any construct or call signatures

What I'm trying to do, in other words, I would like to take the MyButton variable, and inject children into it. How can I do that?

I tried with React.createElement:

{React.createElement(
  MyButton,
  {},
  &lt;div&gt;
    &lt;p&gt;Child element 1&lt;/p&gt;
    &lt;p&gt;Child element 2&lt;/p&gt;
  &lt;/div&gt;
)}

But it doesn't expect a React.ReactNode as type.

The real use case I'm trying to implement:
I'm using the package @react-pdf/renderer, which has a component with which you can wrap a button for example, and then clicking on that button will generate PDF.

In my composition I'm trying to implement it by using two separate components, one that passes the PDF generator component of a PDF library (in this example, react-pdf renderer), and another component, that doesn't know about which library is being used. The second component will use get the PDF generator component and just wrap it around a button.

First component:

import { PDFDownloadLink } from &#39;@react-pdf/renderer&#39;;

export default function FirstComponent() {
  return (
    &lt;SecondComponent
      {...props}
      downloadPdfElement={
        &lt;PDFDownloadLink
          document={&lt;MyPdfDoc pdfTimelineRows={pdfTimelineRows} /&gt;}
          fileName=&quot;pdf&quot;
        /&gt;
      }
    /&gt;
  );
}

The second component should just uses the prop downloadPdfElement and wrap it around some button.

Again, this can all easily be done in one component, just wrap the PDFDownloadLink around a button and that's it, but I'd like to make it into two separate components. If it's too complex to achieve then it's also an answer

答案1

得分: 1

以下是您要翻译的内容:

在您的编辑之后,我建议定义一个新的组件,该组件将在PDFDownloadLink中包装props.children,这样您可以随时调用该包装组件,并渲染一个带有自定义props的PDFDownloadLink

DownloadWrapper可以扩展以添加更多的props以适应您的需求。

// Demo, imported from Lib
const PDFDownloadLink = (props) => {
    return <button>{props.children}</button>;
}

// Wrapper download button
const DownloadWrapper = (props) => {
    return <PDFDownloadLink>{props.children}</PDFDownloadLink>;
}

const Example = () => {
    return (
        <div>
            <h1>{'Example'}</h1>
            <DownloadWrapper>
                <div>
                    <p>Child element 1</p>
                    <p>Child element 2</p>
                </div>
            </DownloadWrapper>
        </div>
    )
}
ReactDOM.render(<Example />, document.getElementById("react"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="react"></div>
英文:

After your edit, I'd suggest defining a new component, that will wrap props.children in a PDFDownloadLink, that way you can call that wrapper component anytime, and render a PDFDownloadLink with some custom props.

The DownloadWrapper can be extended to add more props to fit your needs.

<!-- begin snippet: js hide: false console: true babel: true -->

<!-- language: lang-js -->

// Demo, imported from Lib
const PDFDownloadLink = (props) =&gt; {
    return &lt;button&gt;{props.children}&lt;/button&gt;;
}

// Wrapper download button
const DownloadWrapper = (props) =&gt; {
    return &lt;PDFDownloadLink&gt;{props.children}&lt;/PDFDownloadLink&gt;;
}

const Example = () =&gt; {
    return (
        &lt;div&gt;
            &lt;h1&gt;{&#39;Example&#39;}&lt;/h1&gt;
            &lt;DownloadWrapper&gt;
                &lt;div&gt;
                    &lt;p&gt;Child element 1&lt;/p&gt;
                    &lt;p&gt;Child element 2&lt;/p&gt;
                &lt;/div&gt;
             &lt;/DownloadWrapper&gt;
        &lt;/div&gt;
    )
}
ReactDOM.render(&lt;Example /&gt;, document.getElementById(&quot;react&quot;));

<!-- language: lang-html -->

&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js&quot;&gt;&lt;/script&gt;
&lt;div id=&quot;react&quot;&gt;&lt;/div&gt;

<!-- end snippet -->

huangapple
  • 本文由 发表于 2023年4月13日 19:22:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/76004839.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定