React CurrencyInput使用customInput时出现Ref警告问题排查
问题
我尝试在React的CurrencyInput字段中渲染自定义输入组件,目前编写的代码如下:
import { TextField, TextFieldProps } from '@mui/material'; import React from 'react'; import CurrencyInput from 'react-currency-input-field'; import { Controller, RegisterOptions, useFormContext } from 'react-hook-form'; type IProps = { name: string; rules?: RegisterOptions; defaultValue?: string; }; type Props = IProps & TextFieldProps; export default function RHFCurrencyField({ name, rules, defaultValue, ...other }: Props) { const { control } = useFormContext(); return ( <Controller name={name} rules={rules} control={control} render={({ field, fieldState: { error } }) => ( <CurrencyInput name={name} groupSeparator=" " defaultValue={defaultValue} decimalsLimit={2} onValueChange={(value, name) => { field.onChange(value); }} customInput={() => <CurrencyTextField {...other} {...field} />} /> )} /> ); } export const CurrencyTextField = React.forwardRef((props: Props, ref: any) => { return <TextField {...props} ref={ref} />; });
但我收到了如下警告:
react-dom.development.js:67 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 CurrencyInput.
请问我遗漏了什么?
解决方案
问题出在customInput的传参逻辑上:react-currency-input-field的customInput需要接收组件类型,而不是你现在传的返回组件的匿名函数。当你传函数时,CurrencyInput内部尝试给这个函数组件绑定ref,但函数本身不是forwardRef包装的合法组件,因此触发了警告。
直接修改以下几个关键点即可解决:
import { TextField, TextFieldProps } from '@mui/material'; import React from 'react'; import CurrencyInput from 'react-currency-input-field'; import { Controller, RegisterOptions, useFormContext } from 'react-hook-form'; type IProps = { name: string; rules?: RegisterOptions; defaultValue?: string; }; type Props = IProps & TextFieldProps; export default function RHFCurrencyField({ name, rules, defaultValue, ...other }: Props) { const { control } = useFormContext(); return ( <Controller name={name} rules={rules} control={control} render={({ field, fieldState: { error } }) => ( <CurrencyInput name={name} groupSeparator=" " defaultValue={defaultValue} decimalsLimit={2} onValueChange={(value) => { field.onChange(value); }} // 直接传递forwardRef包装好的组件类型 customInput={CurrencyTextField} // 通过customInputProps传递所有需要的属性 customInputProps={{ ...other, ...field, error: !!error, helperText: error?.message }} /> )} /> ); } // 明确ref类型,并且用inputRef传递给TextField的底层输入框 export const CurrencyTextField = React.forwardRef<HTMLInputElement, TextFieldProps>((props, ref) => { return <TextField {...props} inputRef={ref} />; });
核心修改说明:
- 把
customInput={() => <CurrencyTextField ... />}改为customInput={CurrencyTextField},直接传递组件本身,而非返回组件的函数。 - 使用
customInputProps统一传递自定义组件需要的所有属性,包括react-hook-form的field、MUI的other以及表单错误状态。 - 修正
CurrencyTextField的ref处理:MUI的TextField是复合组件,ref指向外层容器,需要用inputRef才能把ref传递到底层的<input>元素上,同时明确ref的类型为HTMLInputElement。
这样修改后,CurrencyInput内部就能正确将ref传递给CurrencyTextField,彻底解决ref绑定的警告问题。
内容的提问来源于stack exchange,提问作者Wings
相关产品推荐
相关产品推荐

