为何使用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
相关产品推荐
相关产品推荐

