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

CoreUI+React Hook Form报错:函数组件无法接收refs问题求助

解决React Hook Form + CoreUI组件的Ref警告问题

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 CSelect or CInputFile—just spread the register props onto them.
  • Use the errors object to toggle the is-invalid class, so your validation feedback shows up correctly when the field has errors.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:25:45