You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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} />;
});

核心修改说明:

  1. 把customInput={() => <CurrencyTextField ... />}改为customInput={CurrencyTextField},直接传递组件本身,而非返回组件的函数。
  2. 使用customInputProps统一传递自定义组件需要的所有属性,包括react-hook-form的field、MUI的other以及表单错误状态。
  3. 修正CurrencyTextField的ref处理:MUI的TextField是复合组件,ref指向外层容器,需要用inputRef才能把ref传递到底层的<input>元素上,同时明确ref的类型为HTMLInputElement。

这样修改后,CurrencyInput内部就能正确将ref传递给CurrencyTextField,彻底解决ref绑定的警告问题。

内容的提问来源于stack exchange,提问作者Wings

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 09:55:26