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

使用react-hook-form提交表单后,email和password值返回undefined

React Hook Form 提交后表单值为undefined的解决方法

问题描述

使用ReactJS、TypeScript和styled-components开发登录页面,通过react-hook-form处理表单逻辑,表单仅包含邮箱和密码输入字段。提交表单后console.log输出的email和password均为undefined,浏览器控制台无报错信息。

核心原因

你给两个InputField都传递了同一个外部ref,覆盖了react-hook-form通过register生成的内部ref,导致表单无法捕获输入框的值。react-hook-form的register方法会自动为输入框绑定用于跟踪值的ref,手动传递外部ref会破坏这一机制。

解决方案

方案1:移除不必要的外部ref

如果不需要父组件控制输入框的ref,直接删除InputField上的ref={ref}属性即可:

import React from "react";
import { useForm, SubmitHandler } from "react-hook-form";
import { Form, TitleSecondary } from "./Form.style";
import { Button } from "../Button/Button";
import { InputContainer, InputLabel, InputField } from "./Form.style";

interface IForm {
  email: string;
  password: string;
}

// 移除forwardRef,因为不需要传递外部ref
export const FormLogin = () => {
  const { register, handleSubmit } = useForm<IForm>();

  const onSubmit: SubmitHandler<IForm> = (data) => console.log(data);

  return (
    <Form onSubmit={handleSubmit(onSubmit)}>
      <TitleSecondary>Login</TitleSecondary>
      <InputContainer>
        <InputLabel htmlFor="email">Email</InputLabel>
        <InputField
          {...register("email")}
          id="email"
          type="email"
          placeholder=""
          required
        />
      </InputContainer>
      <InputContainer>
        <InputLabel htmlFor="password">Password</InputLabel>
        <InputField
          {...register("password")}
          id="password"
          type="password"
          placeholder="mail@example.com"
          required
        />
      </InputContainer>
      <Button />
    </Form>
  )
}

方案2:为每个输入框分配独立的ref

如果确实需要父组件控制输入框(比如邮箱输入框自动聚焦),给每个输入框分配独立的ref,避免覆盖react-hook-form的内部ref:

import React, { useRef } from "react";
import { useForm, SubmitHandler } from "react-hook-form";
import { Form, TitleSecondary } from "./Form.style";
import { Button } from "../Button/Button";
import { InputContainer, InputLabel, InputField } from "./Form.style";

interface IForm {
  email: string;
  password: string;
}

export const FormLogin = React.forwardRef<HTMLInputElement>((props, ref) => {
  const { register, handleSubmit } = useForm<IForm>();
  // 为密码输入框创建独立的ref
  const passwordRef = useRef<HTMLInputElement>(null);

  const onSubmit: SubmitHandler<IForm> = (data) => console.log(data);

  return (
    <Form onSubmit={handleSubmit(onSubmit)}>
      <TitleSecondary>Login</TitleSecondary>
      <InputContainer>
        <InputLabel htmlFor="email">Email</InputLabel>
        <InputField
          {...register("email")}
          id="email"
          type="email"
          placeholder=""
          ref={ref} // 仅给邮箱输入框传递外部ref
          required
        />
      </InputContainer>
      <InputContainer>
        <InputLabel htmlFor="password">Password</InputLabel>
        <InputField
          {...register("password")}
          id="password"
          type="password"
          placeholder="mail@example.com"
          ref={passwordRef} // 密码输入框使用独立ref
          required
        />
      </InputContainer>
      <Button />
    </Form>
  )
})

补充说明

  • register方法返回的对象包含react-hook-form用于跟踪输入值的ref,手动覆盖这个ref会导致表单无法关联输入框的内容。
  • 你的代码中输入框的id与register的字段名保持一致,这部分是正确的,无需修改。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 04:39:34