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

React+Axios+Express表单提交失败及未使用变量警告修复

Fixes for Your React + Express Contact Form Issues

Let's break down each problem and fix them step by step to get your contact form sending emails properly:

1. Fix Form Submission Default Behavior (Page Refresh Issue)

The core reason your page refreshes and appends form data to the URL is that you attached the onSubmit handler to a FormGroup instead of the root Form component. Browsers trigger the default GET form submission when the submit button is clicked if the onSubmit isn't bound to the actual form element—so your e.preventDefault() was never even running!

Fix: Move the onSubmit prop to the Form component, and correct the event type in handleSubmit (it should be React.FormEvent<HTMLFormElement>, not HTMLInputElement).

2. Fix State Updates in handleChange

Right now, your handleChange sets both email and message state values to the same input value. That means whichever field you type in last will overwrite the other. Instead, use the input's name attribute to target the correct state field.

3. Fix Axios Request Structure & Unused Variable Warning

You're wrapping email and message in extra objects when sending the POST request, which makes the backend receive nested data (like req.body.email.email instead of req.body.email). Also, the form variable was assigned but never used—either remove the assignment or use it to handle the response (like logging success).

4. Backend Improvements

  • Access form data correctly once the frontend sends it properly
  • Send a response back to the frontend after processing the email (otherwise the request will hang)
  • Use async/await for cleaner, more readable nodemailer code

Corrected Frontend App.tsx

import React, { Component } from "react";
import { Button, Form, FormGroup, Label, Input } from "reactstrap";
import axios from "axios";

class App extends Component {
  state = { email: "", message: "" };

  handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
    // Use input's name attribute to update the correct state field
    this.setState({ [e.target.name]: e.target.value } as Pick<typeof this.state, string>);
  };

  async handleSubmit(e: React.FormEvent<HTMLFormElement>) {
    e.preventDefault(); // Now works correctly since it's bound to the form

    try {
      // Send state directly without extra nesting
      const response = await axios.post("/api/form", {
        email: this.state.email,
        message: this.state.message,
      });
      console.log("Email sent successfully:", response.data);
      // Reset form after success
      this.setState({ email: "", message: "" });
    } catch (error) {
      console.error("Error sending email:", error);
    }
  }

  render() {
    return (
      <>
        <div>
          {/* Move onSubmit to the Form component */}
          <Form id="contact-form" onSubmit={this.handleSubmit} method="POST">
            <FormGroup>
              <Label for="email">Email</Label>
              {/* Add name attribute matching state key */}
              <Input
                type="email"
                name="email"
                id="email"
                placeholder="with a placeholder"
                value={this.state.email}
                onChange={this.handleChange}
              />
            </FormGroup>
            <FormGroup>
              <Label for="message">Message</Label>
              {/* Add name attribute matching state key */}
              <Input
                type="textarea"
                name="message"
                id="message"
                placeholder="with a placeholder"
                value={this.state.message}
                onChange={this.handleChange}
              />
            </FormGroup>
            <Button type="submit">Submit</Button>
          </Form>
        </div>
      </>
    );
  }
}

export default App;

Corrected Backend index.ts

import express, { Application, Request, Response } from "express";
import bodyParser from "body-parser";
import nodemailer from "nodemailer";

const app: Application = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));

app.post("/api/form", async (req: Request, res: Response) => {
  try {
    // Initialize transporter with async/await
    const transporter = nodemailer.createTransport({
      host: "smtp.ethereal.email",
      port: 587,
      auth: {
        user: "MY_TEST_EMAIL_NAME", // Replace with your Ethereal username
        pass: "MY_TEST_EMAIL_PASSWORD", // Replace with your Ethereal password
      },
    });

    const htmlEmail = `
      <h3>Contact details</h3>
      <ul>
        <li>Email: ${req.body.email}</li>
      </ul>
      <h3>Message</h3>
      <p>${req.body.message}</p>
    `;

    const mailOptions = {
      from: "test@testaccount.com",
      to: "MY_TEST_EMAIL_NAME",
      replyTo: req.body.email, // Use user's email for replies
      subject: "New Message from Contact Form",
      text: req.body.message,
      html: htmlEmail,
    };

    const info = await transporter.sendMail(mailOptions);
    console.log("Message sent: %s", info.messageId);
    console.log("Preview URL: %s", nodemailer.getTestMessageUrl(info));

    // Send success response to frontend
    res.status(200).json({ success: true, message: "Email sent successfully" });
  } catch (err) {
    console.error("Error sending email:", err);
    res.status(500).json({ success: false, error: "Failed to send email" });
  }
});

const PORT = 5000;
app.listen(PORT, () => {
  console.log(`Server listening on port ${PORT}`);
});

Quick Additional Checks

  • Add "proxy": "http://localhost:5000" to your frontend's package.json—this lets Axios forward /api/form requests to your backend without needing the full URL.
  • Ethereal emails are for testing only: you won't get real emails in your inbox, but use the preview URL logged in the backend terminal to see what the email looks like. For production, switch to a real SMTP service like SendGrid or Mailgun.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 07:20:27