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

React表单提交后无法重新渲染问题求助

问题诊断与修复

点击提交无反应的核心原因是表单验证未通过,但没有任何错误提示,导致你误以为提交操作没触发。以下是具体问题点和修复方案:

1. 缺少验证错误反馈

你的表单配置了Zod验证,但没有在界面上显示错误信息。当用户输入不符合规则(比如名字太短、没选课程、数字为空或超出范围)时,handleSubmit的回调不会执行,页面自然没有变化。

修复:添加错误显示逻辑

在StudentGradingEvaluationForm.tsx中,从useForm解构formState.errors,然后在每个表单控件下方添加错误提示:

import { z } from "zod";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import courses from "./Courses";

const schema = z.object({
  name: z
    .string()
    .min(3, { message: "姓名至少需要3个字符" }),
  number: z.coerce.number()
    .min(0, { message: "分数不能小于0" })
    .max(100, { message: "分数不能超过100" }),
  courses: z.enum(courses, {
    errorMap: () => ({ message: "请选择课程" }),
  }),
});

export type StudentFormData = z.infer<typeof schema>;

interface Props {
  onSubmit: (data: StudentFormData) => void;
}

const StudentGradingEvaluationForm = ({ onSubmit }: Props) => {
  const { register, handleSubmit, formState: { errors } } = useForm<StudentFormData>({
    resolver: zodResolver(schema),
  });

  return (
    <form
      onSubmit={handleSubmit((data) => {
        onSubmit(data);
      })}
    >
      <div className="mb-3">
        <label htmlFor="studentName" className="form-label">
          学生姓名
        </label>
        <input
          id="studentName"
          type="text"
          className={`form-control ${errors.name ? 'is-invalid' : ''}`}
          {...register("name")}
        />
        {errors.name && <div className="invalid-feedback">{errors.name.message}</div>}
      </div>
      <div className="mb-3">
        <label htmlFor="courseName" className="form-label">
          课程名称
        </label>
        <div>
          <select
            id="courseName"
            className={`form-select ${errors.courses ? 'is-invalid' : ''}`}
            {...register("courses")}
          >
            <option value="" disabled>请选择课程</option>
            {courses.map((course) => (
              <option key={course} value={course}>
                {course}
              </option>
            ))}
          </select>
        </div>
        {errors.courses && <div className="invalid-feedback">{errors.courses.message}</div>}
      </div>
      <div className="mb-3">
        <label htmlFor="number" className="form-label">
          输入分数
        </label>
        <input
          id="number"
          type="number"
          className={`form-control ${errors.number ? 'is-invalid' : ''}`}
          {...register("number")}
        />
        {errors.number && <div className="invalid-feedback">{errors.number.message}</div>}
      </div>
      <button type="submit" className="btn btn-primary">
        提交
      </button>
    </form>
  );
};

export default StudentGradingEvaluationForm;

2. 数字输入的验证问题

原代码中z.number()要求输入必须是有效数字,但当输入框为空时,React Hook Form会返回空字符串'',Zod会判定为验证失败。使用z.coerce.number()可以自动将空字符串、非数字值转换为NaN,配合验证规则可以更友好地处理空输入场景。

3. 课程选择的默认选项问题

原代码中默认选项的value=""是空字符串,不符合z.enum(courses)的枚举值要求,导致未选课程时验证失败。修改为<option value="" disabled>请选择课程</option>,既引导用户选择,又避免空值提交。

额外优化:App.tsx中的逻辑简化

可以简化App.tsx中的状态判断,因为formData存在时必然是提交成功的状态,不需要单独维护isFormSubmitted:

import { useState } from "react";
import StudentGradingEvaluationForm, {
  StudentFormData,
} from "./Components/StudentGradingEvaluationForm";
import GPACalculator from "./Components/GPACalculator";

const App = () => {
  const [formData, setFormData] = useState<StudentFormData | null>(null);

  const handleFormSubmitted = (data: StudentFormData) => {
    setFormData(data);
  };

  const resetForm = () => {
    setFormData(null);
  };

  return (
    <>
      <div style={{ textAlign: "center" }}>
        <h1>学生GPA计算器</h1>
      </div>
      <div>
        {!formData && (
          <StudentGradingEvaluationForm onSubmit={handleFormSubmitted} />
        )}
      </div>
      {formData && (
        <>
          <button className="btn btn-outline-danger mb-3" onClick={resetForm}>
            重置表单
          </button>
          <GPACalculator
            subject={formData.courses}
            number={formData.number}
            name={formData.name}
          />
        </>
      )}
    </>
  );
};

export default App;

修复后,当用户输入不符合规则时,会显示对应的错误提示;验证通过后,页面会正确渲染GPA计算结果。

内容的提问来源于stack exchange,提问作者Hannan Yusuf Khan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 06:48:11