CoreUI+React Hook Form报错:函数组件无法接收refs问题求助
Hey, let's break down why you're seeing that ref warning and fix it up quickly!
为什么会出现这个警告?
The warning pops up because CoreUI's CInput is a function component, and React Hook Form's register tries to pass a DOM ref to it. But function components don't accept refs by default—you need to use React.forwardRef() to let the component pass that ref down to the actual native <input> element inside it.
Luckily, you don't have to build this from scratch. There are two easy ways to fix this:
方案1:直接展开register返回的属性(最省事)
React Hook Form's register method returns an object with onChange, onBlur, name, and ref properties. Instead of passing ref directly, just spread all these props onto the CInput component. CoreUI's components are built to handle these props correctly and pass the ref to the underlying native input.
Modify your CInput code like this:
<CInput className="form-control-success" id="firstName" {...register({ required: true })} // 展开所有register返回的属性 />
This way, you don't have to worry about ref forwarding manually—it all works under the hood.
方案2:手动封装带forwardRef的CoreUI组件(如果方案1不生效)
If for some reason spreading props doesn't work, you can wrap CInput with forwardRef yourself. Note that CoreUI components use innerRef instead of the standard ref prop to pass refs to their internal elements:
import React, { forwardRef } from 'react'; import { CInput } from '@coreui/react'; // 封装一个支持ref的CInput const ForwardedCInput = forwardRef((props, ref) => { return <CInput {...props} innerRef={ref} />; });
Then use this wrapped component in your form:
<ForwardedCInput className="form-control-success" id="firstName" name="firstName" ref={register({ required: true })} />
修正后的完整代码
I also fixed a small issue with useForm initialization—you need to pass defaultValues inside a config object, not directly. Here's your updated component:
import React from 'react'; import { CCard, CCardBody, CCardHeader, CCol, CRow, CForm, CFormGroup, CInput, CLabel, CValidFeedback, CInvalidFeedback, CSelect, CInputFile, CButton, CCardFooter } from '@coreui/react'; import CIcon from '@coreui/icons-react'; import { useForm } from 'react-hook-form'; const defaultValues = { firstName: '', lastName: '', studentBadgeID: '', gender: '', dateOfBirth: '', class: '', religion: '', joiningDate: '', phone: '', admissionNumber: '', email: '', parentName: '', parentAddress: '', parentPhone: '', parentEmail: '' }; const AddStudents = () => { // 修正useForm的参数格式 const { register, handleSubmit, errors } = useForm({ defaultValues }); const onSubmit = data => console.log(data); return ( <CCol xs="12"> <CCard> <CForm onSubmit={handleSubmit(onSubmit)}> <CCardHeader>Add Student</CCardHeader> <CCardBody> <h4>Student Information</h4> <CRow className="my-0"> <CCol lg="6" sm="12"> <CLabel htmlFor="firstName">First Name</CLabel> {/* 使用展开属性的方式注册 */} <CInput className={errors.firstName ? 'is-invalid' : 'form-control-success'} id="firstName" {...register({ required: 'Please enter your first name' })} /> {/* 根据errors动态显示反馈 */} {errors.firstName && ( <CInvalidFeedback className="help-block"> {errors.firstName.message} </CInvalidFeedback> )} {!errors.firstName && ( <CValidFeedback className="help-block"> Input provided </CValidFeedback> )} </CCol> </CRow> </CCardBody> <CCardFooter> <CButton type="submit" size="sm" color="primary" className="mr-1"> <CIcon name="cil-scrubber" /> Submit </CButton> <CButton type="reset" size="sm" color="danger"> <CIcon name="cil-ban" /> Reset </CButton> </CCardFooter> </CForm> </CCard> </CCol> ); }; export default AddStudents;
额外小贴士
- This same approach works for other CoreUI form components like
CSelectorCInputFile—just spread theregisterprops onto them. - Use the
errorsobject to toggle theis-invalidclass, so your validation feedback shows up correctly when the field has errors.
内容的提问来源于stack exchange,提问作者Adrian Brebenel

