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

联系表单发送按钮无法提交,请求技术排查

问题描述

正在开发网站联系表单,用户输入姓名、邮箱与留言后,信息需通过SendGrid API发送至办公邮箱。服务端代码实现于server.js,但点击发送按钮无任何反应。已确认server.js运行正常、SendGrid API密钥有效,表单已绑定onSubmit={submitHandler}。

服务端代码(server.js)

// server.js
const express = require("express");
const sgMail = require("@sendgrid/mail");
const { resolve } = require("path-browserify");

// Set up SendGrid API key
sgMail.setApiKey("***********");

// Create Express app
const app = express();

// Middleware to parse JSON requests
app.use(express.json());

app.get("/", (req, res) => {
  res.send("Hello, server!");
});

// Route to handle sending emails
app.post("/send-email", (req, res) => {
  const { Name, Email, Message, submitbutton } = req.body;

  const msg = {
    to: "******@gmail.com",
    from: "******@gmail.com",
    subject: "Example Subject",
    text: `Name: ${Name}\nEmail: ${Email}\nMessage: ${Message}\nSubmit Button: ${submitbutton}`,
    html: `<p>Name: ${Name}</p><p>Email: ${Email}</p><p>Message: ${Message}</p><p>Submit Button: ${submitbutton}</p>`,
  };

  sgMail
    .send(msg)
    .then(() => {
      res.status(200).json({ message: "Email sent successfully" });
    })
    .catch((error) => {
      console.error(error.toString());
      res.status(500).json({ error: "Failed to send email" });
    });
});

// Set up fallback for path module
resolve.fallback = { path: require.resolve("path-browserify") };

// Start the server
app.listen(4000, () => {
  console.log("Server started on port 3000");
});

客户端代码(card.tsx)

import React, { useState, useEffect, useRef } from "react";
import cardcss from "./Card.module.css";
import axios from "axios";

interface CardProps {
  imageUrl: string;
  title: string;
  body: string;
}

function Card(props: CardProps) {
  const [message, setMessage] = useState("");
  const nameInputRef = useRef<HTMLInputElement>(null);
  const emailInputRef = useRef<HTMLInputElement>(null);
  const messageInputRef = useRef<HTMLInputElement>(null);

  useEffect(() => {
    if (messageInputRef.current) {
      messageInputRef.current.focus();
      messageInputRef.current.setSelectionRange(0, 0);

      // Delay setting the cursor position
      setTimeout(() => {
        messageInputRef.current?.setSelectionRange(0, 0);
      }, 0);
    }
  }, []);

  const handleFocus = (event: React.FocusEvent<HTMLInputElement>) => {
    event.target.setSelectionRange(0, 0);
  };

  const submitHandler = (event: React.FormEvent<HTMLFormElement>) => {
    event.preventDefault();

    if (
      nameInputRef.current &&
      emailInputRef.current &&
      messageInputRef.current
    ) {
      const nameInput = nameInputRef.current.value;
      const emailInput = emailInputRef.current.value;
      const messageInput = messageInputRef.current.value;

      const contactData = {
        Name: nameInput,
        Email: emailInput,
        Message: messageInput,
      };

      axios
        .post("/send-email", contactData)
        .then((response) => {
          console.log(response.data);
          // Handle success response
        })
        .catch((error) => {
          console.error(error);
          // Handle error response
        });
    }
  };

  return (
    // JSX code for the contact form
    // ...
  );
}

export default Card;

排查与解决建议

1. 服务端端口不一致问题

server.js中app.listen(4000)但日志输出Server started on port 3000,会导致你误以为服务运行在3000端口,实际是4000端口,客户端请求可能指向错误端口。

  • 修复:统一端口号,比如把app.listen(4000)改为app.listen(3000),或者修改日志为console.log("Server started on port 4000")。

2. 错误的resolve.fallback配置

代码中resolve.fallback = { path: require.resolve("path-browserify") }是Webpack的配置项,不是Express的API,放在server.js中会抛出TypeError: Cannot set properties of function (setting 'fallback')错误,导致服务无法正常启动。

  • 修复:直接删除这行代码,path-browserify在Node.js环境中不需要额外配置,Express也不需要这个fallback设置。

3. 客户端请求跨域/地址错误

如果React客户端运行在默认的3000端口,而服务端在4000端口,axios.post("/send-email")会请求客户端所在的3000端口,导致跨域问题,请求无法到达服务端。

  • 修复方案二选一:
    • 在React项目的package.json中添加"proxy": "http://localhost:4000"(开发环境有效),axios会自动转发请求到服务端端口。
    • 直接写全请求地址:axios.post("http://localhost:4000/send-email", contactData)。

4. 表单元素与Ref类型不匹配

messageInputRef被定义为HTMLInputElement,但如果表单中留言框是<textarea>元素,ref.current会是null,导致submitHandler中的if条件不满足,代码不会执行发送请求的逻辑。

  • 修复:如果留言框是textarea,修改Ref类型为HTMLTextAreaElement:
    const messageInputRef = useRef<HTMLTextAreaElement>(null);
    
    同时确保JSX中的表单元素正确绑定ref:
    <input type="text" ref={nameInputRef} />
    <input type="email" ref={emailInputRef} />
    <textarea ref={messageInputRef} />
    

5. 额外优化:添加错误日志

如果submitHandler中的if条件不满足,添加日志提示方便排查:

const submitHandler = (event: React.FormEvent<HTMLFormElement>) => {
  event.preventDefault();

  if (
    nameInputRef.current &&
    emailInputRef.current &&
    messageInputRef.current
  ) {
    // 发送请求逻辑
  } else {
    console.error("表单元素Ref未正确绑定");
  }
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 21:37:55