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

React中使用EmailJS提交表单时提示‘公钥无效’的问题排查

EmailJS公钥无效问题排查

我在React项目中使用EmailJS实现表单提交功能时,收到错误提示:

The Public Key is invalid. To find this ID, visit https://dashboard.emailjs.com/admin/account

已确认公钥复制正确,且存储在.env文件中,通过console.log能正常输出该值。以下是项目代码,恳请帮忙排查问题所在:

import React, { useRef, useState, useEffect } from "react"; 
import NavBar from "../NavBar"; 
import { useNavigate } from "react-router-dom"; 
import emailjs from "emailjs-com";

export default function Contact() {   
  const [email, setEmail] = useState("");   
  const [emailError, setEmailError] = useState("");   
  const navigate = useNavigate();   
  const SERVICE_ID = process.env.REACT_APP_SERVICE_ID;   
  const TEMPLATE_ID = process.env.REACT_APP_TEMPLATE_ID;   
  const USER_ID = process.env.REACT_APP_USER_ID;   
  console.log(USER_ID);   
  emailjs.init(process.env.PUBLIC_KEY);

  const goForward = (e) => {
    e.preventDefault();
    if (document.querySelector("form").checkValidity()) {
      navigate("/contact/messagereceived");
    } else {
      // Handle form validation errors
      setEmailError("Please fill in all required fields.");
    }   
  };

  const validateEmail = () => {
    let validRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;

    if (email.match(validRegex)) {
      // Valid email address
      setEmailError("");
    } else if (email === "") {
      setEmailError("Email is empty!");
    } else {
      // Invalid email address
      setEmailError("Invalid email address!");
    }   
  };

  function handleEmailBlur(e) {
    e.preventDefault();
    validateEmail(e.target.value);   
  }

  const formRef = useRef(null);   
  const cleanupPerformedRef = useRef(false);

  useEffect(() => {
    const formElement = formRef.current;

    const handleFormSubmit = (e) => {
      e.preventDefault();
      sendEmail();
    };

    formElement.addEventListener("submit", handleFormSubmit);

    return () => {
      if (!cleanupPerformedRef.current) {
        // Cleanup: remove the event listener
        formElement.removeEventListener("submit", handleFormSubmit);
        cleanupPerformedRef.current = true;
      }
    };   
  }, []);   

  const sendEmail = () => {
    console.log("hey ok i am here");

    emailjs.sendForm(SERVICE_ID, TEMPLATE_ID, formRef.current, USER_ID).then(
      function (response) {
        console.log("SUCCESS!", response.status, response.text);
        navigate("/contact/messagereceived");
      },
      function (error) {
        console.log("FAILED...", error);
      }
    );   
  };

  useEffect(() => {
    const formElement = formRef.current;
    document.body.appendChild(formElement);

    return () => {
      if (!cleanupPerformedRef.current) {
        // Cleanup: remove the form from the body
        document.body.removeChild(formElement);
        cleanupPerformedRef.current = true;
      }
    };   
  }, []);

  return (
    <div className="overall-container">
      <NavBar />
      <article className="about active" data-page="about">
        <header>
          <h2 className="h2 article-title">Contact</h2>
        </header>

        <section className="mapbox" data-mapbox>
          <figure>
            <iframe
              src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d193572.47843136364!2d-74.11808636666852!3d40.70563057829406!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x89c24fa5d33f083b%3A0xc80b8f06e177fe62!2sNew%20York%2C%20NY%2C%20USA!5e0!3m2!1sen!2sbd!4v1647611355151!5m2!1sen!2sbd"
              width="600"
              height="300"
              loading="lazy"
              title="Google Map"
            ></iframe>
          </figure>
        </section>

        <section className="contact-form">
          <h3 className="h3 form-title">Contact Form</h3>

          <form className="form" ref={formRef}>
            <div className="input-wrapper">
              <input
                type="text"
                name="user_name"
                className="form-input"
                placeholder="Example Name"
                required
                data-form-input
              />

              <input
                type="email"
                name="user_email"
                className="form-input"
                placeholder="example@domain.com"
                required
                data-form-input
                value={email}
                onBlur={handleEmailBlur}
                onChange={(e) => setEmail(e.target.value)}
              />
              {emailError && (
                <p className="email-error-message">{emailError}</p>
              )}
            </div>

            <textarea
              name="message"
              className="form-input"
              placeholder="Your Message"
              required
              data-form-input
            ></textarea>

            <button
              className="form-btn"
              onClick={goForward}
              type="submit"
              data-form-btn
              value="Send"
            >
              <span>Send Message</span>
            </button>
          </form>
        </section>
      </article>
    </div>   
  ); 
}

排查方向及解决方案

  • 环境变量命名不符合React规范:React项目中,自定义环境变量必须以REACT_APP_为前缀才能被读取。如果你的.env文件里公钥变量是PUBLIC_KEY,需要修改为REACT_APP_PUBLIC_KEY,并在代码中对应改为process.env.REACT_APP_PUBLIC_KEY。
  • EmailJS初始化参数错误:emailjs.init()方法需要传入的是你的User ID(即代码中定义的USER_ID),而非单独的"公钥"。EmailJS的User ID就是官方所说的公钥,你代码里错误地传入了process.env.PUBLIC_KEY,正确写法应为emailjs.init(USER_ID)。
  • 表单提交逻辑冲突:按钮同时绑定了onClick={goForward}和type="submit",导致sendEmail可能无法触发。建议移除onClick绑定,让表单的submit事件直接调用sendEmail;或者在goForward中验证通过后调用sendEmail,而非直接跳转。
  • 不必要的DOM移动操作:你在useEffect中把表单元素移到body再移除,这可能导致ref引用异常或事件监听失效,建议删除该useEffect逻辑,保持表单在组件正常渲染位置。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 12:28:17