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

使用shadcn库时React表单无法提交的问题求助

问题:Vite+React集成shadcn后表单提交无响应

使用Vite开发React应用,集成shadcn/ui库后表单完全无法提交,但未使用该库时表单功能正常。相关组件代码如下:

Register组件代码

import React from "react";
import { z } from "zod";
import { zodResolver } from "@hookform/resolvers/zod";
import { useForm } from "react-hook-form";
import axios from "axios";
import { useNavigate } from "react-router-dom";
import { Form } from "@/components/ui/form";
import LinkButton from "@/components/Button";
import Navbar from "@/components/Navbar";
import RegisterForm from "@/components/RegisterForm";

const schema = z
  .object({
    username: z.string().min(2),
    password: z.string().min(8),
    confirmPassword: z.string().min(8),
    email: z.string().email(),
  })
  .refine((data) => data.password === data.confirmPassword, {
    message: "Passwords don't match",
    path: ["confirmPassword"],
  });

export const Register = () => {
  const navigate = useNavigate();
  const methods = useForm({
    resolver: zodResolver(schema),
    defaultValues: {
      email: "",
      username: "",
      password: "",
      confirmPassword: "",
    }
  })

  const { handleSubmit, control, formState: { isSubmitting } } = methods;

  const onSubmit = async (values) => {
    console.log("Form values:", values);
    const { username, password, email } = values;
    try {
      console.log("Attempting to register user...");
      const response = await axios.post("/api/auth/register", {
        username,
        email,
        password,
      });
      console.log(response.data);
      navigate("/login");
    } catch (error) {
      console.error("Error during registration:", error);
    }
  };
  console.log("Render Register component");
  return (
    <div>
      <Navbar />
      <div className="flex justify-center items-center h-screen">
        <Form {...methods}>
          <form
            onSubmit={handleSubmit(onSubmit)}
            className="space-y-6 p-4 xl:w-1/2 md:w-1/2 sm:w-1/2 xs:w-full xs:p-5 shadow-md"
          >
            <RegisterForm name="username" label="Username" placeholder="Username" inputType="username" formControl={control}/>
            <RegisterForm name="email" label="Email" placeholder="Email" inputType="email" formControl={control}/>
            <RegisterForm name="password" label="Password" placeholder="Password" inputType="password" formControl={control}/>
            <RegisterForm name="confirmPassword" label="Confirm Password" placeholder="Confirm Password" inputType="password" formControl={control}/>
            <LinkButton
              type="submit"
              className="w-full bg-bg-btn-prm"
              disabled={isSubmitting}
            >
             {isSubmitting ? "Loading..." : "Register"}
            </LinkButton>
          </form>
        </Form>
      </div>
    </div>
  );
};

RegisterForm组件代码

import React from 'react';
import { FormControl, FormField, FormItem, FormLabel, FormMessage } from './ui/form';
import { Input } from './ui/input';

const RegisterForm = React.memo(({ name, label, placeholder, inputType = 'text', formControl }) => {
  console.log(`Rendering field: ${name}`);

  return (
    <FormField control={formControl} name={name} render={({ field }) => (
      <FormItem>
        <FormLabel>{label}</FormLabel>
        <FormControl>
          <Input placeholder={placeholder} type={inputType} {...field} />
        </FormControl>
        <FormMessage />
      </FormItem>
    )} />
  );
});

export default RegisterForm;

问题排查与解决方案

核心原因

shadcn/ui的<Form>组件已经封装了react-hook-form的上下文和表单处理逻辑,你在它内部嵌套原生<form>标签,导致提交事件被拦截,无法正确触发handleSubmit。

修复方案

移除原生<form>标签,将提交逻辑直接绑定到shadcn的<Form>组件上,调整后的Register组件核心部分如下:

// ...其他代码不变
return (
  <div>
    <Navbar />
    <div className="flex justify-center items-center h-screen">
      <Form 
        {...methods} 
        onSubmit={handleSubmit(onSubmit)}
        className="space-y-6 p-4 xl:w-1/2 md:w-1/2 sm:w-1/2 xs:w-full xs:p-5 shadow-md"
      >
        <RegisterForm name="username" label="Username" placeholder="Username" inputType="username" formControl={control}/>
        <RegisterForm name="email" label="Email" placeholder="Email" inputType="email" formControl={control}/>
        <RegisterForm name="password" label="Password" placeholder="Password" inputType="password" formControl={control}/>
        <RegisterForm name="confirmPassword" label="Confirm Password" placeholder="Confirm Password" inputType="password" formControl={control}/>
        <LinkButton
          type="submit"
          className="w-full bg-bg-btn-prm"
          disabled={isSubmitting}
        >
         {isSubmitting ? "Loading..." : "Register"}
        </LinkButton>
      </Form>
    </div>
  </div>
);

额外检查项

  • 确认LinkButton组件实际渲染为原生<button>元素,且type="submit"属性未被覆盖
  • 验证shadcn/ui的Form组件版本与react-hook-form版本兼容

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 04:26:03