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

React表单验证通过后无法使用Email.js发送的问题解决

React表单验证与Email.js发送修复方案

问题描述

我在React应用中尝试在表单验证完成后通过Email.js发送表单数据,但即使没有错误,表单也无法发送。需求是:

  • 若至少一个字段未填写,显示错误提示且不发送表单
  • 所有字段填写完成后,发送表单并向用户展示成功提示

原代码如下:

import React, { useState, useRef, useEffect } from "react";
import "../CSS/form.css";
import Checkbox from "./Checkbox";
import emailjs from "@emailjs/browser";

const Form = () => {
  const formRef = useRef();
  const initialValues = {
    panna_mloda: "",
    pan_mlody: "",
    numer_kontaktowy: "",
    email: "",
    data: "",
    miejsce_slubu: "",
    miejsce_wesela: "",
    goscie: "",
    budzet: "",
  };
  const [formValues, setFormValues] = useState(initialValues);
  const [formErrors, setFormErrors] = useState({});
  const [isSubmit, setIsSubmit] = useState(false);

  const handleChange = (e) => {
    const { name, value } = e.target;
    setFormValues({ ...formValues, [name]: value });
  };

  const validate = (values) => {
    const errors = {};
    if (!values.panna_mloda) {
      errors.panna_mloda = "Proszę wprowadzić imię Panny młodej";
    }
    if (!values.pan_mlody) {
      errors.pan_mlody = "Proszę wprowadzić imię Pana młodego";
    }
    if (!values.numer_kontaktowy) {
      errors.numer_kontaktowy = "Proszę wprowadzić numer kontaktowy";
    }
    if (!values.email) {
      errors.email = "Proszę wprowadzić adres mailowy";
    }
    if (!values.data) {
      errors.data = "Proszę wprowadzić datę ślubu";
    }
    if (!values.miejsce_slubu) {
      errors.miejsce_slubu = "Proszę wprowadzić miejsce ślubu";
    }
    if (!values.miejsce_wesela) {
      errors.miejsce_wesela = "Proszę wprowadzić miejsce wesela";
    }
    if (!values.goscie) {
      errors.goscie = "Proszę wprowadzić przewidywaną liczbę gości";
    }
    if (!values.budzet) {
      errors.budzet = "Proszę wprowadzić planowany budżet na dekorację";
    }

    return errors;
  };

  const handleSubmit = (e) => {
    e.preventDefault();
    setFormErrors(validate(formValues));
    setIsSubmit(true);
    if (Object.keys(formErrors).length === 0 && isSubmit) {
      emailjs
        .sendForm(
          "service_*****",
          "template_*****",
          formValues.current,
          "2aRB3MFBn*****"
        )
        .then(
          (result) => {
            console.log(result.text);
          },
          (error) => {
            console.log(error.text);
          }
        );
    }
  };

  useEffect(() => {
    console.log(formErrors);
    if (Object.keys(formErrors).length === 0 && isSubmit) {
      console.log(formValues);
    }
  }, [formErrors]);

问题分析与修复步骤

  1. 状态更新异步导致判断失效:setFormErrors是异步操作,在handleSubmit中直接判断formErrors长度时,状态还未更新,无法得到正确的验证结果。
  2. Email.js参数错误:sendForm需要传入DOM表单元素(formRef.current),而非状态对象formValues(它没有current属性)。
  3. 缺失用户反馈:原代码没有成功/失败的用户提示逻辑。

修改后的完整代码

import React, { useState, useRef, useEffect } from "react";
import "../CSS/form.css";
import Checkbox from "./Checkbox";
import emailjs from "@emailjs/browser";

const Form = () => {
  const formRef = useRef();
  const initialValues = {
    panna_mloda: "",
    pan_mlody: "",
    numer_kontaktowy: "",
    email: "",
    data: "",
    miejsce_slubu: "",
    miejsce_wesela: "",
    goscie: "",
    budzet: "",
  };
  const [formValues, setFormValues] = useState(initialValues);
  const [formErrors, setFormErrors] = useState({});
  const [isSubmit, setIsSubmit] = useState(false);
  const [submitSuccess, setSubmitSuccess] = useState(false); // 新增成功状态

  const handleChange = (e) => {
    const { name, value } = e.target;
    setFormValues({ ...formValues, [name]: value });
    // 输入时清除成功提示
    if (submitSuccess) setSubmitSuccess(false);
  };

  const validate = (values) => {
    const errors = {};
    // 增加trim处理,过滤纯空格输入
    if (!values.panna_mloda.trim()) {
      errors.panna_mloda = "Proszę wprowadzić imię Panny młodej";
    }
    if (!values.pan_mlody.trim()) {
      errors.pan_mlody = "Proszę wprowadzić imię Pana młodego";
    }
    if (!values.numer_kontaktowy.trim()) {
      errors.numer_kontaktowy = "Proszę wprowadzić numer kontaktowy";
    }
    if (!values.email.trim()) {
      errors.email = "Proszę wprowadzić adres mailowy";
    }
    if (!values.data.trim()) {
      errors.data = "Proszę wprowadzić datę ślubu";
    }
    if (!values.miejsce_slubu.trim()) {
      errors.miejsce_slubu = "Proszę wprowadzić miejsce ślubu";
    }
    if (!values.miejsce_wesela.trim()) {
      errors.miejsce_wesela = "Proszę wprowadzić miejsce wesela";
    }
    if (!values.goscie.trim()) {
      errors.goscie = "Proszę wprowadzić przewidywaną liczbę gości";
    }
    if (!values.budzet.trim()) {
      errors.budzet = "Proszę wprowadzić planowany budżet na dekorację";
    }

    return errors;
  };

  const handleSubmit = (e) => {
    e.preventDefault();
    // 同步获取验证结果,避免异步状态更新延迟
    const errors = validate(formValues);
    setFormErrors(errors);
    setIsSubmit(true);
  };

  useEffect(() => {
    if (isSubmit && Object.keys(formErrors).length === 0) {
      // 验证通过,发送邮件
      emailjs
        .sendForm(
          "service_*****",
          "template_*****",
          formRef.current, // 修正为表单DOM元素
          "2aRB3MFBn*****"
        )
        .then(
          (result) => {
            console.log(result.text);
            setSubmitSuccess(true);
            // 发送成功后重置表单
            setFormValues(initialValues);
            setIsSubmit(false);
          },
          (error) => {
            console.log(error.text);
            alert("Wystąpił błąd podczas wysyłania formularza, spróbuj ponownie.");
            setIsSubmit(false);
          }
        );
    } else if (isSubmit) {
      // 验证不通过,重置提交状态
      setIsSubmit(false);
    }
  }, [formErrors, isSubmit]);

  return (
    <form ref={formRef} onSubmit={handleSubmit}>
      {/* Panna młoda字段示例,其他字段按相同逻辑渲染 */}
      <div className="form-group">
        <label>Panna młoda</label>
        <input
          type="text"
          name="panna_mloda"
          value={formValues.panna_mloda}
          onChange={handleChange}
        />
        {formErrors.panna_mloda && <span className="error">{formErrors.panna_mloda}</span>}
      </div>

      {/* 其他字段省略,请按照上述示例补充 */}

      {/* 成功提示 */}
      {submitSuccess && <div className="success-message">Formularz wysłany pomyślnie!</div>}

      <button type="submit">Wyślij formularz</button>
    </form>
  );
};

export default Form;

关键修改说明

  • 同步验证结果:在handleSubmit中直接调用validate获取错误对象,避免异步状态更新导致的判断延迟。
  • 修正Email.js参数:将formValues.current改为formRef.current,确保传入正确的DOM表单元素。
  • 新增用户反馈:添加submitSuccess状态展示成功消息,发送失败时弹出提示框。
  • 优化验证逻辑:用trim()过滤纯空格输入,避免无效提交。
  • 表单重置:发送成功后自动清空表单,提升用户体验。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 20:05:33