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

为何使用React Hook Form注册同名组件时出现ref相关警告?

解决React Hook Form自定义单选按钮的Ref警告问题

问题原因

React Hook Form的register方法会返回包含ref属性的对象,用于关联表单控件以跟踪值和状态。但你的ToggleButton是函数组件,默认不支持接收ref,导致React抛出"Function components cannot be given refs"警告。

解决方案

需要用React.forwardRef将ref转发到自定义组件内部的原生单选按钮(input[type="radio"]),因为原生表单元素才是表单值的实际载体,自定义组件仅负责UI渲染。

1. 修改自定义ToggleButton组件

import React, { forwardRef } from 'react';

// 用forwardRef包裹组件,接收外部传入的ref并转发给内部原生input
const ToggleButton = forwardRef(({ value, name, onChange, children, position, ...rest }, ref) => {
  return (
    <label style={{ display: 'inline-block' }}>
      {/* 隐藏原生radio,仅作为表单值的载体 */}
      <input
        type="radio"
        name={name}
        value={value}
        onChange={onChange}
        ref={ref}
        style={{ display: 'none' }}
      />
      {/* 自定义UI按钮 */}
      <div 
        style={{
          padding: '8px 16px',
          cursor: 'pointer',
          border: '1px solid #ccc',
          backgroundColor: rest.checked ? '#2196F3' : '#fff',
          color: rest.checked ? '#fff' : '#333',
          ...(position === 'left' ? { borderTopLeftRadius: '4px', borderBottomLeftRadius: '4px' } : {}),
          ...(position === 'right' ? { borderTopRightRadius: '4px', borderBottomRightRadius: '4px' } : {})
        }}
        onClick={() => ref.current?.click()}
      >
        {children}
      </div>
    </label>
  );
});

// 必须设置displayName,避免React devtools显示异常
ToggleButton.displayName = 'ToggleButton';

export default ToggleButton;

2. 调整表单中的使用方式

不需要手动维护选中状态(比如isERC1155),原生radio会自动管理选中状态,React Hook Form会通过register获取选中值:

import { useForm } from 'react-hook-form';
import ToggleButton from './ToggleButton';

interface FormInput {
  dynamicFieldTitle: string;
  formTitle: string;
  tokenType: "ERC1155" | "ERC721";
  tokenAddress: string;
  tokenId: string;
  expirationDate: string;
}

function NewForm() {
  const { register, handleSubmit } = useForm<FormInput>();

  const onSubmit = (data: FormInput) => {
    console.log('表单数据:', data);
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      {/* 其他表单字段 */}
      <div style={{ display: 'flex', margin: '16px 0' }}>
        <ToggleButton
          {...register("tokenType")}
          value="ERC721"
          position="left"
        >
          ERC721
        </ToggleButton>
        <ToggleButton
          {...register("tokenType")}
          value="ERC1155"
          position="right"
        >
          ERC1155
        </ToggleButton>
      </div>
      <button type="submit">提交表单</button>
    </form>
  );
}

export default NewForm;

关键说明

  • forwardRef让自定义组件能够接收并传递ref到内部的原生表单元素,满足React Hook Form的ref绑定需求。
  • 隐藏的原生radio负责处理表单值的同步,自定义UI仅作为交互入口,既符合表单原生行为,又满足自定义UI需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 12:20:39