React函数组件(Functional Component)/JSX中作为参数的嵌套组件

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

Nested component as argument in React FC / JSX

问题

我有一个在React FC类型Script中的结构:

import { BaseLayout } from "./...."
import { MainContent } from "./...."
import { SplitContent } from "./...."
import { VideoFeed } from "./...."
...

<Route path="/foo" element={<BaseLayout ContentComponent={MainContent}/>} />

这部分工作正常。

然而,其中一个子组件应该是另一个嵌套的组件,但我似乎无法使其工作。

<Route path="/foo" element={<BaseLayout ContentComponent={MainContent}/>} />

MainContent 不接受任何属性/参数,但 SplitContent 期望类似以下的东西:

export function SplitContent({ TopContent }: { TopContent: FC }) { ... }

(我只是试图让它工作,显然它将稍后接受第二个底部组件作为参数,但首先让它能够与一个组件一起工作)。

因此,如果我尝试将 SplitContent 作为组件传递而不是字符串,TypeScript 会报错:

<Route path="/foo" element={<BaseLayout ContentComponent={<SplitContent />} />} />

"Type Element is not assignable to type FC<{}>"

(除了 SplitContent 没有接收预期的 TopContent 参数)。

如果我使用 ts-ignore 抑制它,那么在控制台中它不会呈现,我会得到以下错误:

"React.jsx: 类型无效 - 期望字符串(对于内置组件)或类/函数(对于组合组件),但实际得到: "

英文:

I have this structure in React FC typescript:

import { BaseLayout } from &quot;./....&quot;
import { MainContent } from &quot;./....&quot;
import { SplitContent } from &quot;./....&quot;
import { VideoFeed } from &quot;./....&quot;
...

&lt;Route path=&quot;/foo&quot; element={&lt;BaseLayout ContentComponent={MainContent}/&gt;}

That works fine.

However, one of the child component is supposed to be another nested component, and I can't seem to make it work.

&lt;Route path=&quot;/foo&quot; element={&lt;BaseLayout ContentComponent={MainContent}/&gt;}

MainContent takes no props/arguments, but SplitContent expects something like:

export function SplitContent({TopContent}: {TopContent: FC}) { ... }

(I'm just trying to make it work, obv it'll later take a 2nd bottom component as argument but let's just make it work with one first).

So if I try to just pass the SplitContent as component, not a string, TS complains:

&lt;Route path=&quot;/foo&quot; element={&lt;BaseLayout ContentComponent={&lt;SplitContent/&gt;}/&gt;}

&quot;Type Element isn not assignable to type FC&lt;{}&gt;&quot;

(On top of SplitContent not receiving an expected TopContent argument).

If I suppress it with ts-ignore, then in the console it doesn't render and I get:

&quot; React.jsx: type is invalid -- expected a string (for built-in component) or a class/function (for composite component) but got: &lt;SplitContent/&gt; &quot;

答案1

得分: 2

在这里,你需要提供一个组件,而不是一个已渲染的元素。注意到以下部分:

() =&gt; &lt;WrapperComponent WrappedComponent={SomeConcreteComponent}/&gt;

这是一个组件,它最终会渲染某些内容,而不是已渲染的东西。

我建议,如果可能的话,不要在渲染中创建它。将它创建为一个新组件,位于你的主要组件之外,然后在这里使用,像这样:

const MyComponent = () =&gt; &lt;WrapperComponent WrappedComponent={SomeConcreteComponent}/&gt;;

// 在你的主要组件内部
&lt;Route
  path=&quot;/foo&quot;
  element={
    &lt;BaseLayout
      ContentComponent={MyComponent}
    /&gt;
  }
/&gt;
英文:

There is a difference between a component (a function/class which might have state, and is likely to return some elements) and rendered elements (&lt;Foo /&gt;). In this case, what you need to provide is a component. Not a rendered element:

&lt;Route
  path=&quot;/foo&quot;
  element={
    &lt;BaseLayout
      ContentComponent={() =&gt; (
        &lt;WrapperComponent WrappedComponent={SomeConcreteComponent} /&gt;
      )}
    /&gt;
  }
/&gt;

notice that

() =&gt; &lt;WrapperComponent WrappedComponent={SomeConcreteComponent}/&gt;

is a component which in turn, renders something. It's not the rendered thing.

I'd suggest not making it in render though, if possible.
Create it outside of your main component as a new component. And use it here. Like:

const MyComponent = () =&gt; &lt;WrapperComponent WrappedComponent={SomeConcreteComponent}/&gt;;

// And inside your main component
&lt;Route
  path=&quot;/foo&quot;
  element={
    &lt;BaseLayout
      ContentComponent={MyComponent}
    /&gt;
  }
/&gt;

huangapple
  • 本文由 发表于 2023年2月10日 02:42:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/75403087.html
匿名

发表评论

匿名网友

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

确定