React + TypeScript语法:动态更改容器组件

时间:2019-01-30 19:41:14

标签: reactjs typescript

在React + TypeScript下面是否有一种干净的方法来编写这种语法?当我这样做时,出现以下错误。

JSX element type 'Container' does not have any construct or call signatures.

代码:

const Container = this.props.useFoo ? <Foo {...fooProps}></Foo> : <div></div>;

return (
        <Container>
            <div {...someAttrs}>
                {this.props.children}
            </div>
        </Container>
);

我知道我可以使用字符串Tag = "div"动态定义容器标签,并使用<Tag>...</Tag>,但这似乎不适用于组件。我这样做的唯一方法是将子级内容保存到变量中,然后执行以下操作,使它变得冗长且丑陋。

const content = <div {...someAttrs}>{this.props.children}</div>;

return (
    <>
        {this.props.useFoo ? <Foo {...fooProps}>{content}</Foo> : <div>{content}</div>}
    </>
);

编辑:

我决定采用以下语法:

const container = (content) => {
    return this.props.useFoo ? <Foo {...fooProps}>{content}</Foo> : <div>{content}</div>;
};

return container(
    <div {...someAttrs}>
        {this.props.children}
    </div>
);

2 个答案:

答案 0 :(得分:2)

请注意,我刚开始使用“ TypeScript”(使用React)。

似乎您正在将渲染的Component实例分配给Container,而不是指定容器的形状(类)应该是什么。

因此,您需要传递类或内部字符串"div"并将容器设置为React.ReactType(可以是类,功能组件或内部组件,例如div,{ {1}},p等)。

span

您可以在Sandbox上查看演示。

Edit so.answer.54448317


如果沙盒链接无法正常工作,请提供完整的源代码。

代码

function Demo(props: DemoProps) {
  const Container: React.ReactType = props.useFoo ? Foo : "div";

  return (
    <Container>
      <div>{props.children}</div>
    </Container>
  );
}

结果

demo result

☝您可以看到使用import * as React from "react"; import { render } from "react-dom"; import "./styles.css"; interface DemoProps { useFoo?: boolean; children: string | JSX.Element | JSX.Element[]; } const Foo = () => <div>Foo</div>; function Demo(props: DemoProps) { const Container: React.ReactType = props.useFoo ? Foo : "div"; return ( <Container> <div>{props.children}</div> </Container> ); } function App() { return ( <div> <Demo useFoo>This is a demo App</Demo> <Demo>This is a demo App</Demo> </div> ); } const rootElement = document.getElementById("root"); render(<App />, rootElement); 时容器重写了子级内容。

答案 1 :(得分:0)

第一个示例的问题是,要传递已渲染的组件,而不是对其的引用(稍后将进行渲染),则解决该问题的方法是:

// imports ...

function Foo(props) {
  console.log('using foo')
  return <main>{props.children}</main>
}

function Baz(props) {
  console.log('using baz')
  return <div>{props.children}</div>
}

function ConditionalComponent(props) {
  const Container = props.useFoo ? Foo : Baz;

  return (
    <Container>
      {props.children}
    </Container>
  )
}