input
尝试通过 MUI 的InputUnstyled
组件(或任何其他非样式组件,例如SwitchUnstyled
,SelectUnstyled
等),我收到警告
Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?
Check the render method of `ForwardRef`.
InputElement@http://localhost:3000/main.4c2d885b9953394bb5ec.hot-update.js:59:45
div
...
我使用components
prop 在我自己的MyStyledInput
组件中定义一个自定义Input
元素,该元素包装 MUIInputUnstyled
:
import InputUnstyled, {
InputUnstyledProps
} from '@mui/base/InputUnstyled';
const MyStyledInput: React.FC<InputUnstyledProps> = props => {
const { components, ...otherProps } = props;
return (
<InputUnstyled
components={{
Input: InputElement,
...components,
}}
{...otherProps}
/>
);
};
我的自定义input
组件InputElement
导致Function components cannot be given refs
警告:
import {
InputUnstyledInputSlotProps,
} from '@mui/base/InputUnstyled';
import { Box, BoxProps } from '@mui/material';
const InputElement: React.FC<BoxProps & InputUnstyledInputSlotProps> = (
{ ownerState, ...props }
) => {
return (
<Box
component="input"
// any style customizations
{...props}
ref={ref}
/>
);
});
注意:我正在使用component="input
使 MUI 的Box
组件不是呈现 HTMLdiv
而是呈现 DOM 中的 HTMLinput
组件。
为什么我会收到此警告?
此处、此处和此处的其他相关问题解决了类似的问题,但不适用于 MUI 无样式组件。这些线程也没有解释为什么
警告要求您查看InputElement
组件。老实说,堆栈跟踪在这里有点误导。它说:
检查
ForwardRef
的渲染方法。 InputElement@http://localhost:3000/main.4c2d885b9953394bb5ec.hot-update.js:59:45 迪夫
您可以忽略此处的ForwardRef
。内部InputElement
由
理解此警告的关键部分是:
不能为函数组件提供引用。尝试访问此引用将失败。
也就是说,如果有人尝试通过ref
访问 DOM 中的实际 HTMLinput
元素(Material UI 实际上尝试这样做),它将不会成功,因为功能组件InputElement
无法将该ref
传递给input
元素(此处通过 MUIBox
组件创建)。
因此,警告继续显示:
你的意思是使用 React.forwardRef() 吗?
这提出了用React.forwardRef
包装函数组件的解决方案。forwardRef
使您可以掌握ref
并将其传递给实际的input
组件(在本例中是带有道具component="input"
的Box
组件)。它应该看起来像这样:
import {
InputUnstyledInputSlotProps,
} from '@mui/base/InputUnstyled';
import { Box, BoxProps } from '@mui/material';
const InputElement = React.forwardRef<
HTMLInputElement,
BoxProps & InputUnstyledInputSlotProps
>(({ ownerState, ...props }, ref) => {
const theme = useTheme();
return (
<Box
component="input"
// any style customizations
{...props}
ref={ref}
/>
);
});
为什么我首先要处理ref
?
如果是 HTMLinput
元素,您很有可能希望通过ref
访问它的 DOM 节点。如果您将 Reactinput
组件用作不受控制的组件,则会出现这种情况。不受控制的输入组件将其状态(即用户在该输入字段中输入的任何内容)保存在实际的 DOM 节点中,而不是在React.useState
钩子的状态值内。如果通过React.useState
挂钩控制输入值,则将输入用作受控组件。
注: 具有type="file"
的输入始终是不受控制的组件。这在 React 文档部分关于文件输入标签的解释。