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

React应用中Bootstrap表单首次点击Submit不触发问题求助

问题核心

你的问题出在React状态更新是异步的:在sendEmail函数里,调用setValidated(true)后马上判断validated === true,此时validated还没完成更新,第一次点击时不会执行邮件发送逻辑;第二次点击时validated已经变成true,才会触发发送,所以需要双击才能成功。

解决方案1:直接用表单验证结果(推荐)

不用依赖validated状态判断是否发邮件,直接拿表单checkValidity()的返回值,验证通过就立即调用email.js,逻辑更直接:

import React, { useState, useRef } from "react";
import { Col, Button, Form, Card, InputGroup } from "react-bootstrap";
import emailjs from "@emailjs/browser";

const ContactForm = () => {
  const refForm = useRef();
  const [validated, setValidated] = useState(false);

  const sendEmail = (e) => {
    e.preventDefault();
    e.stopPropagation();

    const form = e.currentTarget;
    // 先检查表单是否有效
    const isFormValid = form.checkValidity();
    // 设置validated状态,触发Bootstrap的错误提示样式
    setValidated(true);

    if (isFormValid) {
      // 验证通过,执行email.js发送逻辑
      emailjs.sendForm('你的服务ID', '你的模板ID', refForm.current, '你的公钥')
        .then((result) => {
          console.log("邮件发送成功:", result.text);
          // 可选:发送成功后重置表单
          form.reset();
          setValidated(false);
        }, (error) => {
          console.log("邮件发送失败:", error.text);
        });
    }
  };

  return (
    <Form
      ref={refForm}
      onSubmit={sendEmail}
      autoComplete="on"
      noValidate
      validated={validated}
    >
      <Form.Label>全名*</Form.Label>
      <Form.Group>
        <InputGroup hasValidation>
          <Form.Control
            name="name"
            type="text"
            required
            minLength={3}
            maxLength={20}
          />
          <Form.Control.Feedback type="invalid">
            请输入至少3个字符的全名
          </Form.Control.Feedback>
        </InputGroup>
      </Form.Group>

      <Form.Label>邮箱地址*</Form.Label>
      <Form.Group>
        <InputGroup hasValidation>
          <Form.Control
            name="email"
            type="email"
            required
          />
          <Form.Control.Feedback type="invalid">
            请输入有效的邮箱格式
          </Form.Control.Feedback>
        </InputGroup>
      </Form.Group>

      <Button type="submit" value="send">
        提交
      </Button>
    </Form>
  );
};

export default ContactForm;
解决方案2:用useEffect监听状态

如果一定要用useEffect,可以监听validated和表单提交状态,当两者都满足时触发发送:

import React, { useState, useRef, useEffect } from "react";
import { Col, Button, Form, Card, InputGroup } from "react-bootstrap";
import emailjs from "@emailjs/browser";

const ContactForm = () => {
  const refForm = useRef();
  const [validated, setValidated] = useState(false);
  const [isSubmitted, setIsSubmitted] = useState(false);

  // 监听validated和isSubmitted状态变化
  useEffect(() => {
    if (validated && isSubmitted) {
      // 验证通过且表单已提交,执行发送
      emailjs.sendForm('你的服务ID', '你的模板ID', refForm.current, '你的公钥')
        .then((result) => {
          console.log("邮件发送成功:", result.text);
          // 重置状态,避免重复触发
          setIsSubmitted(false);
          refForm.current.reset();
          setValidated(false);
        }, (error) => {
          console.log("邮件发送失败:", error.text);
          setIsSubmitted(false);
        });
    }
  }, [validated, isSubmitted]);

  const sendEmail = (e) => {
    e.preventDefault();
    e.stopPropagation();

    const form = e.currentTarget;
    const isFormValid = form.checkValidity();
    setValidated(true);

    if (isFormValid) {
      // 标记表单已提交,触发useEffect
      setIsSubmitted(true);
    }
  };

  return (
    <Form
      ref={refForm}
      onSubmit={sendEmail}
      autoComplete="on"
      noValidate
      validated={validated}
    >
      {/* 表单内容和方案1一致 */}
      <Form.Label>全名*</Form.Label>
      <Form.Group>
        <InputGroup hasValidation>
          <Form.Control
            name="name"
            type="text"
            required
            minLength={3}
            maxLength={20}
          />
          <Form.Control.Feedback type="invalid">
            请输入至少3个字符的全名
          </Form.Control.Feedback>
        </InputGroup>
      </Form.Group>

      <Form.Label>邮箱地址*</Form.Label>
      <Form.Group>
        <InputGroup hasValidation>
          <Form.Control
            name="email"
            type="email"
            required
          />
          <Form.Control.Feedback type="invalid">
            请输入有效的邮箱格式
          </Form.Control.Feedback>
        </InputGroup>
      </Form.Group>

      <Button type="submit" value="send">
        提交
      </Button>
    </Form>
  );
};

export default ContactForm;
关键提醒
  • React状态更新是异步操作,不要在调用setState后立刻读取该状态的值做判断,这时候值还没更新
  • Bootstrap的validated属性只是用来控制错误提示的显示,不需要用它来决定是否执行发送逻辑
  • 优先选方案1,逻辑更简洁,避免额外的状态监听

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 22:08:12