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

React + EmailJS 在onClick方法中重复发送大量邮件及404路由跳转问题排查

解决你的React表单邮件重复发送和页面跳转问题

嘿,这两个都是React开发里常见的小陷阱,我来帮你一一搞定!

问题1:邮件发送数十封的原因及解决

你现在的按钮onClick写的是this.sendEmail()——注意这里的括号!这会导致组件每次渲染(包括输入字符触发state更新后的重渲染)都会立即调用sendEmail函数,而不是只在点击按钮时执行。所以每输入一个字符就发一封邮件,自然会收到几十封。

解决核心是:把函数引用传递给onClick,而不是立即执行它,同时要确保this的指向正确(类组件的方法默认不会自动绑定组件实例)。这里有三种常用方案:

方式1:在构造函数中绑定this

在constructor里添加绑定代码,一次性搞定this指向:

constructor(){
  super()
  this.state = {
    fromName:'',
    message:'',
    fromEmail:''
  }
  // 绑定this到sendEmail方法
  this.sendEmail = this.sendEmail.bind(this)
}

然后按钮的onClick改成:

<input type="submit" value="Send Message" className="special" onClick={this.sendEmail}/>

方式2:用箭头函数定义sendEmail

把sendEmail改成类的箭头函数属性,this会自动绑定到组件实例:

sendEmail = () => {
  const serviceId='...'
  const templateId='...'
  const userId='...'
  emailjs.send(serviceId, templateId, this.state, userId)
}

按钮同样用onClick={this.sendEmail}即可。

方式3:在onClick中用箭头函数包裹(简单但不推荐大组件用)

<input type="submit" value="Send Message" className="special" onClick={() => this.sendEmail()}/>

这种方式每次渲染都会创建新的箭头函数,小组件没问题,但大型组件可能影响性能,优先选前两种。

问题2:点击按钮后跳转/#并404的解决

这是因为你的按钮是type="submit",点击后会触发表单的默认提交行为——表单的action="#"会让页面跳转到当前URL的/#位置,而Gatsby的路由系统匹配不到这个路径,所以出现404。

推荐两种解决方案:

方案1:阻止表单默认提交,用onSubmit处理

修改表单标签,添加onSubmit事件,阻止默认行为并调用sendEmail,这更符合表单语义:

<form method="post" action="#" onSubmit={(e) => {
  e.preventDefault() // 阻止默认提交跳转
  this.sendEmail()
}}>

然后把按钮的onClick属性去掉,因为表单的submit事件会在点击submit按钮时自动触发。

方案2:把按钮改成type="button"

如果不想用表单的submit事件,直接把按钮类型改成button,这样就不会触发表单默认提交:

<input type="button" value="Send Message" className="special" onClick={this.sendEmail}/>

修改后的完整代码示例

这里用「构造函数绑定this + 表单onSubmit」的方案,你可以直接参考:

import React from 'react'
import emailjs from 'emailjs-com'
class Main extends React.Component {
  constructor(){
    super()
    this.state = {
      fromName:'',
      message:'',
      fromEmail:''
    }
    this.sendEmail = this.sendEmail.bind(this)
  }
  render() {
    return (
      <div>
        <article>
          <form method="post" action="#" onSubmit={(e) => {
            e.preventDefault()
            this.sendEmail()
          }}>
            <div className="field half first">
              <label htmlFor="name">Name</label>
              <input type="text" name="name" id="name" value={this.state.fromName} onChange={e => this.setState({fromName: e.target.value})}/>
            </div>
            <div className="field half">
              <label htmlFor="email">Email</label>
              <input type="text" name="email" id="email" value={this.state.fromEmail} onChange={e => this.setState({fromEmail: e.target.value})}/>
            </div>
            <div className="field">
              <label htmlFor="message">Message</label>
              <textarea name="message" id="message" rows="4" value={this.state.message} onChange={e => this.setState({message: e.target.value})} placeholder = "..."></textarea>
            </div>
            <ul className="actions">
              <li>
                <input type="submit" value="Send Message" className="special"/>
              </li>
            </ul>
          </form>
        </article>
      </div>
    )
  }
  sendEmail() {
    const serviceId='...'
    const templateId='...'
    const userId='...'
    emailjs.send(serviceId, templateId, this.state, userId)
  }
}
export default Main

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 18:34:10