无法渲染,REACT

Unable to render, REACT

提问人:Hannan Yusuf Khan 提问时间:11/12/2023 最后编辑:VLAZHannan Yusuf Khan 更新时间:11/15/2023 访问量:45

问:

我是 Web 开发和学习 React 的新手。我使用ZOD进行表单实现。我的IDE没有显示任何错误,但是当我单击提交按钮时,屏幕没有重新渲染。如果有人能帮助我就好了。我知道这是一个小问题,但我已经挠了一天多了。

APP.TSX
import { useEffect, useState } from "react";
import StudentGradingEvaluationForm, {
  StudentFormData,
} from "./Components/StudentGradingEvaluationForm";
import GPACalculator from "./Components/GPACalculator";
import "./Components/Courses";

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

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

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

  return (
    <>
      <div style={{ textAlign: "center" }}>
        <h1>GPA Calculator for Individual Student</h1>
      </div>
      <div>
        {!isFormSubmitted && (
          <StudentGradingEvaluationForm onSubmit={handleFormSubmitted} />
        )}
        {isFormSubmitted && !formData && (
          <p className="text-danger">Enter correct credentials</p>
        )}
      </div>
      {formData && (
        <button className="btn btn-outline-danger" onClick={resetForm}>
          Reset Form
        </button>
      )}
      {formData && formData.courses && (
        <GPACalculator
          subject={formData.courses}
          number={formData.number}
          name={formData.name}
        />
      )}
    </>
  );
};

export default App;
StudentGradingEvaluationForm.tsx

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: "Description should be atleast 3 characters." }),
  number: z.number().min(0).max(100),
  courses: z.enum(courses, {
    errorMap: () => ({ message: "Course is required." }),
  }),
});

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

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

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

  return (
    <form
      onSubmit={handleSubmit((data) => {
        onSubmit(data);
        console.log(onSubmit);
      })}
    >
      <div className="mb-3">
        <label htmlFor="studentName" className="form-label">
          Name of Student
        </label>
        <input
          id="studentName"
          type="text"
          className="form-control"
          {...register("name")}
        />
      </div>
      <div className="mb-3">
        <label htmlFor="courseName" className="form-label">
          Name of Course
        </label>
        <div>
          <select
            id="courseName"
            className="select-control"
            {...register("courses")}
          >
            <option value=""></option>
            {courses.map((course) => (
              <option key={course} value={course}>
                {course}
              </option>
            ))}
          </select>
        </div>
      </div>
      <div className="mb-3">
        <label htmlFor="number" className="form-label">
          Enter Number
        </label>
        <input
          id="number"
          type="number"
          className="form-control"
          {...register("number")}
        />
      </div>
      <button type="submit" className="btn btn-primary">
        Submit
      </button>
    </form>
  );
};

export default StudentGradingEvaluationForm;
Courses.ts

const courses = [
  "Mechanics of Materials - I",
  "Fluid Dynamics - I",
  "Ordinary Differential Equations",
  "Thermodynamics - II",
  "Basic Electrical and Electronics Engineering",
] as const;

export default courses;
GPACalculator.tsx

interface Props {
  subject: string;
  name: string;
  number: number;
}
const GPACalculator = ({ subject, number, name }: Props) => {
  const calculateGpa = () => {
    if (number < 100 && number >= 80) return "A";
    else if (number < 80 && number >= 65) return "B";
    else if (number < 65 && number >= 55) return "C";
    else if (number < 55 && number >= 40) return "D";
    else return "FAIL";
  };
  return (
    <div>
      <h2>GPA Calculator Result for {name}</h2>
      <p>Subject: {subject}</p>
      <p>Number: {number}</p>
      <p>GPA: {calculateGpa()}</p>
    </div>
  );
};

导出默认 GPACalculator;

我使用了以下依赖项:

npm 创建 [email protected] npm i 引导 npm i zod npm 我 [email protected] npm 我@hookform/[email protected]

VS Code 未显示任何错误。一旦我点击提交按钮,什么也没发生。我相信我的代码简单且不言自明。期待帮助。

ReactJS TypeScript 渲染 Zod

评论


答:

0赞 Obydul Islam Khan 11/12/2023 #1

所以问题是,你的代码没有错误。您的代码工作正常。但是您有 zod 解析器的表单验证错误。由于您没有显示任何表单错误,因此您无法在此处看到问题。

附加您当前代码收到的错误 -enter image description here

如何解决:

<input
      id="number"
      type="text"
      className="form-control"
      {...register("number", {
        valueAsNumber: true,
      })}
    />

只需注册数字输入,就像我在这里显示的那样。

另一件事:

const { register, handleSubmit, formState: { errors } } = useForm({
resolver: zodResolver(schema),});
console.log("errors =====>", errors)

StudentGradingEvaluationForm 组件顶部的代码中更新这些行,以查看错误状态日志。

0赞 Ganesh Shinde 11/12/2023 #2

默认情况下,react-hook-form 将输入值视为字符串

我将架构z.number()更新为z.coerce.number()

const schema = z.object({
  name: z.string().min(3, { message: "Description should be atleast 3 characters." }),
  number: z.coerce
    .number()
    .min(1, { message: "number is less than 1" })
    .max(100, { message: "number is more than 100" }),
  courses: z.enum(courses, {
    errorMap: () => ({ message: "Course is required." }),
  }),
});

我添加消息是为了更好地理解

  <form
      onSubmit={handleSubmit((data) => {
        onSubmit(data);
        console.log(onSubmit);
      })}>
      <div className='mb-3'>
        <label htmlFor='studentName' className='form-label'>
          Name of Student
        </label>
        <input id='studentName' type='text' className='form-control' {...register("name")} />
        <span className='text-danger d-block  mt-2'>{formState.errors?.name?.message}</span>
      </div>
      <div className='mb-3'>
        <label htmlFor='courseName' className='form-label'>
          Name of Course
        </label>
        <div>
          <select id='courseName' className='select-control' {...register("courses")}>
            <option value=''></option>
            {courses.map((course) => (
              <option key={course} value={course}>
                {course}
              </option>
            ))}
          </select>

          <span className='text-danger d-block  mt-2'>{formState.errors?.courses?.message}</span>
        </div>
      </div>
      <div className='mb-3'>
        <label htmlFor='number' className='form-label'>
          Enter Number
        </label>
        <input id='number' type='number' className='form-control' {...register("number")} />
        <span className='text-danger d-block  mt-2'>{formState.errors?.number?.message}</span>
      </div>
      <button type='submit' className='btn btn-primary'>
        Submit
      </button>
    </form>