如何将 `props.children` 转换为 JSX 元素?

nul*_*omo 5 typescript reactjs

使用 React 函数式组件,我们可以像这样渲染子组件:

import React from 'react';

const MyComponent = (props: React.PropsWithChildren) => {
    return props.children;
}
Run Code Online (Sandbox Code Playgroud)

但是,当我使用它时,我收到错误:

...
    return <MyComponent />;
...
Run Code Online (Sandbox Code Playgroud)

或者

...
    return (
        <MyComponent>
            <div>hello</div>
        </MyComponent>
    );
...
Run Code Online (Sandbox Code Playgroud)

导致

'MyComponent' cannot be used as a JSX component. Its return type 'ReactNode' is not a valid JSX element. Type 'undefined' is not assignable to type 'Element | null'.
Run Code Online (Sandbox Code Playgroud)

一种解决方案是将功能组件的返回值包装在片段中:

const MyComponent = (props: React.PropsWithChildren) => {
    return <>{props.children}</>; // <= useless fragment is here
}
Run Code Online (Sandbox Code Playgroud)

但是,然后我触发了eslint: react/jsx-no-useless-fragment错误。

有没有办法使用孩子让我不会遇到这些问题?

编辑

这是游乐场链接

除了使用片段之外,还有其他方法可以从 ReactNode 转换为有效的 JSX 组件吗?

附加说明eslint-plugin-react 有一个allowExpressions涵盖此用例的选项。本质上,当片段执行ReactNode=> JSX 元素转换工作时,它将允许“无用”片段。

nul*_*omo 3

“无用”片段实际上与调用相同

React.createElement(React.Fragment, null, props.children);
Run Code Online (Sandbox Code Playgroud)

React.createElement能够使用组件类型 ( React.Fragment) 和子级来创建具有这些子级的该类型的 JSX 元素。

所以解决方案是这样做:

const MyComponent = (props: React.PropsWithChildren) => {
    return React.createElement(React.Fragment, null, props.children);
}
Run Code Online (Sandbox Code Playgroud)

这让 TS 和 eslint 都很高兴。然而,JSX 比createElement. 启用 eslint 规则选项{"allowExpressions": true}(有关更多详细信息,请参阅问题)并使用 JSX 样式片段是此处的最佳选择。

感谢大家的帮助。