[英]Why does custom input component cause "Function components cannot be given refs" warning?
在尝试通过MUI 的InputUnstyled
组件(或任何其他无样式组件,例如SwitchUnstyled
、 SelectUnstyled
等)自定义input
组件时,我收到警告
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
属性在我自己的MyStyledInput
组件中定义了一个自定义Input
元素,该组件包装了 MUI InputUnstyled
:
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
组件不呈现 HTML div
而是呈现 DOM 中的 HTML input
组件。
为什么我会收到此警告?
该警告希望您查看InputElement
组件。 老实说,堆栈跟踪在这里有点误导。 它说:
检查
ForwardRef
的渲染方法。 InputElement@http://localhost:3000/main.4c2d885b9953394bb5ec.hot-update.js:59:45 div
您可以在此处忽略ForwardRef
。 内部InputElement
由
理解此警告的关键部分是:
Function 组件不能给出参考。 尝试访问此 ref 将失败。
也就是说,如果有人试图通过ref
访问 DOM 中实际的 HTML input
元素(Material UI 实际上试图这样做),它将不会成功,因为功能组件InputElement
无法将该ref
传递给input
元素(此处通过 MUI Box
组件创建)。
因此,警告继续:
你的意思是使用 React.forwardRef() 吗?
这提出了用React.forwardRef
包装 function 组件的解决方案。 forwardRef
使您可以获取ref
并将其传递给实际的input
组件(在本例中是带有 prop 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
?
对于 HTML input
元素,您很可能希望通过ref
访问它的 DOM 节点。 如果您将 React input
组件用作不受控制的组件,就会出现这种情况。 不受控制的输入组件将其 state(即用户在该输入字段中输入的任何内容)保存在实际的 DOM 节点中,而不是在React.useState
挂钩的 state 值内部。 如果您通过React.useState
挂钩控制输入值,则您将输入用作受控组件。
注意: type="file"
的输入始终是不受控制的组件。 这在关于文件输入标签的 React 文档部分中进行了解释。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.