material-ui 无法将FormControl渲染为React.Fragment,

o4hqfura  于 3个月前  发布在  React
关注(0)|答案(5)|浏览(57)

重复问题

  • 我搜索了现有的问题

最新版本

  • 我测试了最新版本

重现步骤 🕹

链接到实时示例:
https://codesandbox.io/s/zealous-benz-3zmg7x?file=/src/App.tsx
步骤:

  1. 在任何地方使用一个 FormControl 组件
  2. 使它呈现为一个 Fragment
  3. 在控制台中看到错误。

当前行为 😯

它在控制台中产生错误:

Warning: Invalid prop `className` supplied to `React.Fragment`. React.Fragment can only have `key` and `children` props.

预期行为 🤔

没有错误。

上下文 🔦

我这样做是因为我需要 FormControl 在表单元素周围产生额外的元素,这是由于 CSS Grid 的原因。
应用 display: contents 对于 CSS Grid 工作来说是不够的,而 subgrid 不幸的是仍然没有得到广泛的支持。

你的环境 🌎

npx @mui/envinfo

System:
    OS: Windows 10 10.0.19045
  Binaries:
    Node: 18.15.0 - C:\Program Files\nodejs\node.EXE
    Yarn: Not Found
    npm: 9.8.0 - C:\Program Files\nodejs\npm.CMD
  Browsers:
    Chrome: 115.0.5790.102
    Edge: Spartan (44.19041.1266.0), Chromium (114.0.1823.86)
  npmPackages:
    @emotion/react:  11.10.6
    @emotion/styled:  11.10.6
    @mui/base:  5.0.0-alpha.124
    @mui/core-downloads-tracker:  5.11.16
    @mui/material:  5.11.16
    @mui/private-theming:  5.12.0
    @mui/styled-engine:  5.11.16
    @mui/styles:  5.12.0
    @mui/system:  5.11.16
    @mui/types:  7.2.4
    @mui/utils:  5.12.0
    @types/react:  18.2.0
    react:  18.2.0
    react-dom:  18.2.0
    typescript:  4.9.5

我正在使用 Firefox 115,以防万一它有影响。

jum4pzuy

jum4pzuy1#

一个可能的(但愚蠢的)解决方法:

const Noop: React.FC<React.PropsWithChildren> = ({ children }) => (
  <>{children}</>
);

const MyAwesomeFormLine: React.FC = () => {
  <FormControl component={Noop}>
    // Label + Input
  </FormControl>
};

基本上,在 Noop 的位置代替 Fragment,其中 Noop 吃掉了错误,Fragment 通常会发出警告,提醒传递了 props。这并不是非常优雅的方法,但是至少它清理了控制台。

mnemlml8

mnemlml82#

@thany 我非常确定这不能正常工作,因为FormControl需要接收props以实现其预期功能,但Fragment只能接收keychildren,正如错误信息所解释的那样。
我这样做是因为我需要FormControl不在其表单元素周围产生额外的元素,这是由于CSS Grid的原因。
你能分享一下你的用例或者你试图实现的布局吗?

tez616oj

tez616oj3#

每个FormControl包含一个标签和一个输入控件。我(我们和我们的设计师)讨厌abel-inside-or-above-the-control布局,我们必须提供一个经典但经过验证的布局,左边是标签,右边是字段。
如果每个FormControl都生成一个<div>,这是不可能实现的,因为CSS Grid需要所有单元格都是它的子元素才能工作。
目前,对于表单来说,有多个FormControl组件会产生大致如下的伪代码:

<form>
  <div> <!-- FormControl -->
    <label>
    <input>
  <div> <!-- FormControl -->
    <label>
    <input>
  <div> <!-- FormControl -->
    <label>
    <input>

Obne不能将CSS Grid应用于此并期望标签和输入自动成为网格单元格。CSS Grid就是这么工作的。要使它正确地呈现为网格,唯一的正确方法是消除这些div:

<form>
  <> <!-- FormControl -->
    <label>
    <input>
  <> <!-- FormControl -->
    <label>
    <input>
  <> <!-- FormControl -->
    <label>
    <input>

这样一来,标签和输入就成为了表单的子元素,即CSS Grid。
现在,说实话,我不认为FormControl绝对需要将自己渲染为div。为什么?我认为FormControl只是一个空组件,为其包含的表单元素组件提供一些功能。它不需要自己渲染任何东西。它当前确实(或者尝试无论如何😒)这样做,但是为了什么目的?我不需要它的类名存在于HTML结构中,我也肯定不喜欢被限制在每个标签+输入组合都被包裹在另一个元素中 - 我需要并希望不要求这一点。
更一般地说 - UI框架不应该规定应该在其组件外部渲染哪些HTML元素。它永远不应该渲染只有它需要而浏览器不需要的任何HTML元素。任何仅用于功能性的 Package 组件都不应该渲染任何HTML,而只应该为其子组件提供预期的功能。这有很多“应该”,所以请随意提出异议,只要我们能解决上面描述的问题就好啦😉
现在,如果有除了FormControl之外的其他组件,我可以用来替代它,同时仍然为其子输入组件提供状态等,我洗耳恭听关于它的建议。
编辑:
@thany我相当确定这不能像FormControl那样工作,因为FormControl需要接收其预期功能的属性,但Fragment无法接收除keychildren之外的任何内容,正如错误消息所解释的那样。
顺便说一下,如果我字面意义上理解 - FormControl仍然可以接收世界上所有的属性而不渲染任何内容。接收属性与组件返回的内容无关。我相信你明白这一点,但我只是想确保我们都在同一页上。
问题在于FormControl能够告诉它应该渲染哪个组件,盲目地假设它传递给该组件的所有内容,它也可以在自己的回合接收到,这显然是一个不安全的假设。

cpjpxq1n

cpjpxq1n4#

@mj12albert,我认为我们应该允许这样做。FormControl不会设置或依赖事件处理程序。我们可以允许React.Fragmentnull作为component/slots.root,或者添加一个新的属性来控制FormControlRoot是否被渲染。

vktxenjb

vktxenjb5#

@mj12albert,我认为我们应该允许这个。FormControl不会设置或依赖事件处理程序。我们可以允许React.Fragmentnull作为component/slots.root,或者添加一个新的prop来控制FormControlRoot是否被渲染。
我更倾向于后者,因为完全有可能构建一个组件,它也不能接受className prop或其他FormControl试图传递的属性。添加一些严格的propType验证,它也可能像Fragment中的错误一样输出一个错误。

相关问题