Node.js/React 表单提交
Node.js/React Form submission
所以我在我的网站上建立了一个联系表单,但我的表单不会提交。端口 5000 和 8080 都不起作用。我正在使用 Node.js、Express、nodemailer 和 cors。我已经尝试了各种方法,例如不同的端口、确保端口已打开、更改本地主机详细信息、在文件树中移动文件等。我完全不知所措。
代码如下:
联系表:
import React, { useState} from 'react'
// import "./contact.scss"
const ContactForm = () => {
const [status, setStatus] = useState("Submit");
const handleSubmit = async (e) => {
e.preventDefault();
setStatus("Sending...");
const { name, email, message } = e.target.elements;
let details = {
name: name.value,
email: email.value,
message: message.value,
};
let response = await fetch("http://localhost:8080/contact", {
method: "POST",
headers: {
"Content-Type": "application/json;charset=utf-8",
},
body: JSON.stringify(details),
});
setStatus("Submit");
let result = await response.json();
alert(result.status);
};
return (
<div className="right">
<div className="rightcontainer">
<h3>Your Information Below</h3>
<form onSubmit={handleSubmit}>
<div>
<label htmlFor="name">Name:</label>
<input
style={
{width: '100%',
height: '40px',
margin: '10px'}
} className='name' type="text" id="name" placeholder="Name" required />
</div>
<div>
<label htmlFor="email">Email:</label>
<input
style={
{width: '100%',
height: '40px',
margin: '10px'}
} className='email' type="email" id="email" placeholder="Email" required />
</div>
<div>
<label htmlFor="message">Message:</label>
<textarea
style={
{width: '100%',
height: '100px',
margin: '10px',
}
} id="message" placeholder="message" required />
</div>
<button
style={
{width: '100%',
height: '40px',
margin: '10px'}
} type="submit" className='button'>{status}</button>
</form>
</div>
</div>
);
}
export default ContactForm
Server.js 文件:
const express = require("express");
const router = express.Router();
const cors = require("cors");
const nodemailer = require("nodemailer");
const app = express();
app.use(cors());
app.use(express.json());
app.use("/", router);
app.listen(8080, () => console.log("Server Running"));
const contactEmail = nodemailer.createTransport({
service: 'gmail',
auth: {
user: "************@gmail.com",
pass: "************",
},
});
contactEmail.verify((error) => {
if (error) {
console.log(error);
} else {
console.log("Ready to Send");
}
});
router.post("/contact", (req, res) => {
const name = req.body.name;
const email = req.body.email;
const message = req.body.message;
const mail = {
from: name,
to: "************@gmail.com",
subject: "Contact Form Submission",
html: `<p>Name: ${name}</p>
<p>Email: ${email}</p>
<p>Message: ${message}</p>`,
};
contactEmail.sendMail(mail, (error) => {
if (error) {
res.json({ status: "ERROR" });
} else {
res.json({ status: "Message Sent" });
}
});
});
联系页面:
import "./contact.scss"
import ContactForm from "../../ContactForm";
import {Mail, GitHub, LinkedIn} from '@material-ui/icons/';
import React from 'react';
export default function Contact() {
return (
<div className='contact' id="contact">
<div className="left">
<div className="leftContainer">
<div className="imgContainer">
<Mail className="people"/>
</div>
<h2>Contact Me</h2>
<p>
If you would like to hire me on a contractual basis or hire me on a per project basis please use the form, alternatively contact me through:
</p>
<div className="icons">
<a href="https://www.linkedin.com/in/jake-gliddon-5199481b7/"><LinkedIn className="icon"/></a>
<a href="https://github.com/jake-gliddon"><GitHub className="icon" /></a>
</div>
</div>
</div>
<div className="right">
<div className="rightContainer mobile">
<ContactForm />
</div>
</div>
</div>
)
}
任何帮助将不胜感激!
好的,所以我认为您的问题出在后端的 /contact
路由中。在路由器回调函数中,您试图访问字符串的属性 name
、email
和 message
,而不是对象。在您的 ContactForm
组件中,您有这一行:body: JSON.stringify(details),
。这意味着在后端您需要将此 JSON 解析为可读的 javascript 对象,如下所示:JSON.parse(req.body)
。这是完整的代码:
router.post("/contact", (req, res) => {
// short for Parsed Body
const pB = JSON.parse(req.body);
const name = pB.name;
const email = pB.email;
const message = pB.message;
const mail = {
from: name,
to: "************@gmail.com",
subject: "Contact Form Submission",
html: `<p>Name: ${name}</p>
<p>Email: ${email}</p>
<p>Message: ${message}</p>`,
};
contactEmail.sendMail(mail, (error) => {
if (error) {
res.json({ status: "ERROR" });
} else {
res.json({ status: "Message Sent" });
}
});
});
此外,如果您想要一种更简单的方法来从客户端发出 POST 请求,我建议您使用库 axios.
至于您的文件结构,它应该如下所示:
那么你应该打开两个终端 windows。在一个中你启动你的反应应用程序:
/client $ npm start
然后在另一个中启动服务器
/server $ node server.js
它们都应该由 npm 单独启动,所以创建一个 server
目录,然后将你的 server.js
文件移到那里,并安装你的依赖项。与 client
目录相同。
此外,我建议在 public 存储库中为您的电子邮件详细信息使用环境变量。尝试在您的服务器中使用 dotenv。
当我尝试 运行 server.js 文件时,出现无效登录错误。这可能只是在我这边,但它可能是您需要解决的下一个问题。我还必须将端口从 5000
切换到 8080
,如果您正在使用 mac,则此端口上可能有某种类型的服务 运行。
所以我在我的网站上建立了一个联系表单,但我的表单不会提交。端口 5000 和 8080 都不起作用。我正在使用 Node.js、Express、nodemailer 和 cors。我已经尝试了各种方法,例如不同的端口、确保端口已打开、更改本地主机详细信息、在文件树中移动文件等。我完全不知所措。
代码如下:
联系表:
import React, { useState} from 'react'
// import "./contact.scss"
const ContactForm = () => {
const [status, setStatus] = useState("Submit");
const handleSubmit = async (e) => {
e.preventDefault();
setStatus("Sending...");
const { name, email, message } = e.target.elements;
let details = {
name: name.value,
email: email.value,
message: message.value,
};
let response = await fetch("http://localhost:8080/contact", {
method: "POST",
headers: {
"Content-Type": "application/json;charset=utf-8",
},
body: JSON.stringify(details),
});
setStatus("Submit");
let result = await response.json();
alert(result.status);
};
return (
<div className="right">
<div className="rightcontainer">
<h3>Your Information Below</h3>
<form onSubmit={handleSubmit}>
<div>
<label htmlFor="name">Name:</label>
<input
style={
{width: '100%',
height: '40px',
margin: '10px'}
} className='name' type="text" id="name" placeholder="Name" required />
</div>
<div>
<label htmlFor="email">Email:</label>
<input
style={
{width: '100%',
height: '40px',
margin: '10px'}
} className='email' type="email" id="email" placeholder="Email" required />
</div>
<div>
<label htmlFor="message">Message:</label>
<textarea
style={
{width: '100%',
height: '100px',
margin: '10px',
}
} id="message" placeholder="message" required />
</div>
<button
style={
{width: '100%',
height: '40px',
margin: '10px'}
} type="submit" className='button'>{status}</button>
</form>
</div>
</div>
);
}
export default ContactForm
Server.js 文件:
const express = require("express");
const router = express.Router();
const cors = require("cors");
const nodemailer = require("nodemailer");
const app = express();
app.use(cors());
app.use(express.json());
app.use("/", router);
app.listen(8080, () => console.log("Server Running"));
const contactEmail = nodemailer.createTransport({
service: 'gmail',
auth: {
user: "************@gmail.com",
pass: "************",
},
});
contactEmail.verify((error) => {
if (error) {
console.log(error);
} else {
console.log("Ready to Send");
}
});
router.post("/contact", (req, res) => {
const name = req.body.name;
const email = req.body.email;
const message = req.body.message;
const mail = {
from: name,
to: "************@gmail.com",
subject: "Contact Form Submission",
html: `<p>Name: ${name}</p>
<p>Email: ${email}</p>
<p>Message: ${message}</p>`,
};
contactEmail.sendMail(mail, (error) => {
if (error) {
res.json({ status: "ERROR" });
} else {
res.json({ status: "Message Sent" });
}
});
});
联系页面:
import "./contact.scss"
import ContactForm from "../../ContactForm";
import {Mail, GitHub, LinkedIn} from '@material-ui/icons/';
import React from 'react';
export default function Contact() {
return (
<div className='contact' id="contact">
<div className="left">
<div className="leftContainer">
<div className="imgContainer">
<Mail className="people"/>
</div>
<h2>Contact Me</h2>
<p>
If you would like to hire me on a contractual basis or hire me on a per project basis please use the form, alternatively contact me through:
</p>
<div className="icons">
<a href="https://www.linkedin.com/in/jake-gliddon-5199481b7/"><LinkedIn className="icon"/></a>
<a href="https://github.com/jake-gliddon"><GitHub className="icon" /></a>
</div>
</div>
</div>
<div className="right">
<div className="rightContainer mobile">
<ContactForm />
</div>
</div>
</div>
)
}
任何帮助将不胜感激!
好的,所以我认为您的问题出在后端的 /contact
路由中。在路由器回调函数中,您试图访问字符串的属性 name
、email
和 message
,而不是对象。在您的 ContactForm
组件中,您有这一行:body: JSON.stringify(details),
。这意味着在后端您需要将此 JSON 解析为可读的 javascript 对象,如下所示:JSON.parse(req.body)
。这是完整的代码:
router.post("/contact", (req, res) => {
// short for Parsed Body
const pB = JSON.parse(req.body);
const name = pB.name;
const email = pB.email;
const message = pB.message;
const mail = {
from: name,
to: "************@gmail.com",
subject: "Contact Form Submission",
html: `<p>Name: ${name}</p>
<p>Email: ${email}</p>
<p>Message: ${message}</p>`,
};
contactEmail.sendMail(mail, (error) => {
if (error) {
res.json({ status: "ERROR" });
} else {
res.json({ status: "Message Sent" });
}
});
});
此外,如果您想要一种更简单的方法来从客户端发出 POST 请求,我建议您使用库 axios.
至于您的文件结构,它应该如下所示:
那么你应该打开两个终端 windows。在一个中你启动你的反应应用程序:
/client $ npm start
然后在另一个中启动服务器
/server $ node server.js
它们都应该由 npm 单独启动,所以创建一个 server
目录,然后将你的 server.js
文件移到那里,并安装你的依赖项。与 client
目录相同。
此外,我建议在 public 存储库中为您的电子邮件详细信息使用环境变量。尝试在您的服务器中使用 dotenv。
当我尝试 运行 server.js 文件时,出现无效登录错误。这可能只是在我这边,但它可能是您需要解决的下一个问题。我还必须将端口从 5000
切换到 8080
,如果您正在使用 mac,则此端口上可能有某种类型的服务 运行。