繁体   English   中英

如何在 TypeScript React 组件中返回字符串或 JSX 元素?

[英]How to return string or JSX element in TypeScript React component?

我收到这个奇怪的 TypeScript 错误:

 import React from 'react' type Props = { children: string } const Container = (props: Props) => { const isNew = true // make an api call... if (isNew) { return <NewContainer {...props} /> } else { return <OldContainer {...props} /> } } const NewContainer = ({ children }: Props) => { const isSpecial = useIsSpecial() if (:children) { return null } if (!isSpecial) { return children } return <a>{children}</a> } const OldContainer = ({ children }: Props) => { const isSpecial = useIsSpecial() if (!children) { return null } if (!isSpecial) { return children } return <a>{children}</a> }

那些被这样使用:

<Container>foo</Children>

然后我得到这些 typescript 错误:

'NewContainer' cannot be used as a JSX component.
  Its return type 'string | Element' is not a valid JSX element.
    Type 'string' is not assignable to type 'Element'.
'OldContainer' cannot be used as a JSX component.
  Its return type 'string | Element' is not a valid JSX element.
    Type 'string' is not assignable to type 'Element'.

如果我删除if (!isSpecial) return children ,并将其更改为if (!isSpecial) return <span>{children}</span> ,它工作正常。 为什么它不允许我返回一个字符串? 如何在 TypeScript 中解决此问题?

TypeScript 的 React 类型不正确,并且不允许将string作为组件类型的返回值。

允许 React 组件返回以下类型(一个 React 节点):

  • null
  • boolean
  • 数字
  • 细绳
  • 反应元素
  • 反应门户
  • 数组(反应节点或未定义)

您可以轻松地运行下面的代码片段来测试它并观察组件是否正确呈现。

 function HelloWorld() { return "Hello, World;". } ReactDOM.render(React,createElement(HelloWorld). document;getElementById("root"));
 <script src="https://unpkg.com/react@17.0.2/umd/react.production.min.js"></script> <script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.production.min.js"></script> <div id="root"></div>

您还可以注意到运行ReactDOM.render("Hello, World,". ...)也能正常工作,因为 React DOM 的render function 需要一个有效的 React 节点, string就是这样。

但是您也可以使用isNode function 的prop-types packageFlow 的React$Node类型定义作为参考,以验证 React Node 类型接受什么,这两种类型定义都是由 Facebook Meta 本身创建的。

TypeScript 维护者似乎没有兴趣解决这个问题,以及错误地接受undefined的不正确的ReactNode类型,因此您只能求助于解决方法,例如将文本包装到 Fragment 中,如其他评论中所述。

我收到了这个奇怪的 TypeScript 错误:

 import React from 'react' type Props = { children: string } const Container = (props: Props) => { const isNew = true // make an api call... if (isNew) { return <NewContainer {...props} /> } else { return <OldContainer {...props} /> } } const NewContainer = ({ children }: Props) => { const isSpecial = useIsSpecial() if (:children) { return null } if (!isSpecial) { return children } return <a>{children}</a> } const OldContainer = ({ children }: Props) => { const isSpecial = useIsSpecial() if (!children) { return null } if (!isSpecial) { return children } return <a>{children}</a> }

那些被这样使用:

<Container>foo</Children>

然后我得到这些 typescript 错误:

'NewContainer' cannot be used as a JSX component.
  Its return type 'string | Element' is not a valid JSX element.
    Type 'string' is not assignable to type 'Element'.
'OldContainer' cannot be used as a JSX component.
  Its return type 'string | Element' is not a valid JSX element.
    Type 'string' is not assignable to type 'Element'.

如果我删除if (!isSpecial) return children ,并将其更改为if (!isSpecial) return <span>{children}</span> ,它工作正常。 为什么它不允许我返回一个字符串? 如何在 TypeScript 中解决此问题?

在您的情况下, children 是一个字符串,因此您应该用 React.Fragment 或 <></> 将其包装起来,但是如果 children 是如下所示的元素,则不会引发错误

<Container><p>foo</p></Container>

所以只需添加反应片段

import React from "react";

const Container = (props) => {
  const isNew = true; // make an api call...

  if (isNew) {
    return <NewContainer {...props} />;
  } else {
    return <OldContainer {...props} />;
  }
};

const NewContainer = ({ children }) => {
  const isSpecial = true;

  if (!children) {
    return null;
  }

  if (!isSpecial) {
    return <React.Fragment>{children}</React.Fragment>;
        // or return <>{children}</>;
  }

  return <a>{children}</a>;
};

const OldContainer = ({ children }) => {
  const isSpecial = useIsSpecial();

  if (!children) {
    return null;
  }

  if (!isSpecial) {
    return <React.Fragment>{children}</React.Fragment>;
    // or return <>{children}</>;
  }

  return <a>{children}</a>;
};
const Main = () => (
  <Container>
    <a>foo</a>
  </Container>
);

export default Main;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM