Having a contact form is obviously better than just simply displaying an email address on your website. Visitors of the website will feel convenient when they get in touch with us via the contact form. Most of the websites have a contact form and when I developed my personal website in React I planned to integrate a contact form, for that I did a Proof of Concept (POC). I have integrated a website using Material UI, Express, and NodeMailer. Material UI is a popular React UI framework like bootstrap. Express is a minimal and flexible Node.js web application framework. Nodemailer is a module for Node.js to send emails. Here we are going to develop a node application and React application from scratch. This is my 31st article in Medium.
拥有联系表格显然比仅在您的网站上显示电子邮件地址更好。 通过联系表与我们联系时,网站访问者会感到很方便。 大多数网站都有联系表,当我在React中开发我的个人网站时,我计划集成一个联系表,为此我进行了概念验证(POC)。 我已经使用Material UI,Express和NodeMailer集成了一个网站。 Material UI是一个流行的React UI框架,例如bootstrap 。 Express是一个最小且灵活的Node.js Web应用程序框架。 Nodemailer是Node.js发送电子邮件的模块。 在这里,我们将从头开始开发节点应用程序和React应用程序。 这是我在Medium中的第31篇文章。
I assume that you know about GitHub. First things first, we need to create two repositories in GitHub. One is for the front-end(React-form) and another is for the back-end (Node API). You could maintain a single repo for both front-end and back-end but that is hard to maintain the project. Next, Download the latest version of node.js from the link. In this article, I used node v12.16.0 and npm version 6.13.4.
我假设您了解GitHub 。 首先,我们需要在GitHub中创建两个存储库。 一个用于前端(React-form),另一个用于后端(Node API)。 您可以为前端和后端都维护一个仓库,但这很难维护项目。 接下来,从链接下载最新版本的node.js。 在本文中,我使用了节点v12.16.0和npm 6.13.4版本。
Photo by Headway on Unsplash Headway在 Unsplash上的 照片To create a react application run the following command in your shell/terminal in a specific folder (e.g., desktop)
要创建一个React应用程序,请在您的Shell /终端的特定文件夹(例如,桌面)中运行以下命令
npx create-react-app contact-formDelete all the files inside the src folder and create an App.js, Contact.js, and index.js files inside the src folder.
删除src文件夹中的所有文件,并在src文件夹中创建App.js,Contact.js和index.js文件。
Now, in your src folder directory you need to create an index.js file with the following code:
现在,在您的src文件夹目录中,您需要使用以下代码创建一个index.js文件:
import React from "react"; import ReactDOM from "react-dom"; import App from "./App"; ReactDOM.render(<App />, document.getElementById("root"));Now, in your src folder directory you need to create an App.js file with the following code:
现在,在您的src文件夹目录中,您需要使用以下代码创建一个App.js文件:
import React from "react"; import Contact from "./Contact"; function App() { return ( <div> <Contact /> </div> ); } export default App;Install Material-UI for Material Design form component.
为材料设计表单组件安装Material-UI。
// Install MaterialUInpm install @material-ui/core --saveInstall Axios to make HTTP requests to the API.
安装Axios以向API发出HTTP请求。
// Install axiosnpm install axios --saveOpen the Contact.js file and Set it up as a class component.
打开Contact.js文件,并将其设置为类组件。
import React, { Component } from "react"; import axios from "axios"; import TextField from "@material-ui/core/TextField"; export default class Contact extends Component { state = { name: "", message: "", email: "", subject: "", sent: false, buttonText: "Send Message", emailError: false, }; // Functions render() { return ( // Form JSX ); } }Contact class component returns JSX form. Here I used Material UI components, so they are optional you can use your own components.
Contact类组件返回JSX表单。 在这里,我使用了Material UI组件,因此它们是可选的,您可以使用自己的组件。
<form className="contact-form" onSubmit={(e) => this.formSubmit(e)}> <TextField id="standard-multiline-flexible" label="Message" placeholder="Enter Message" variant="outlined" multiline rowsMax={4} value={this.state.message} onChange={(e) => this.setState({ message: e.target.value })} required type="text" /> <br /> <br /> <br /> <TextField id="outlined-basic" placeholder="Enter your name" label="Name" variant="outlined" value={this.state.name} onChange={(e) => this.setState({ name: e.target.value })} required type="text" /> <br /> <br /> <br /> <TextField id="outlined-basic" label="Email" placeholder="Enter email address" variant="outlined" value={this.state.email} onChange={(e) => this.handleChangeEmail(e)} error={this.state.emailError} required type="email" /> <br /> <br /> <br /> <TextField id="outlined-basic" placeholder="Enter Subject" label="Subject" variant="outlined" value={this.state.subject} onChange={(e) => this.setState({ subject: e.target.value })} required /> <br /> <br /> <br /> <div className="button--container"> <button type="submit" className="button button-primary"> {this.state.buttonText} </button> </div> </form>Here, except TextField for mail, each TextField has an onChange handler relevant to a specific variable in your component’s state. Therefore, the state gets updated as the input changes. The form itself has an onSubmit handler that calls the formSubmit function which handles your API calls. TextField for mail has an onChange handler that calls the handleChangeEmail function which validates mail TextField inputs.
在这里,除了TextField的邮件,每一TextField具有相关的在组件的状态的特定变量的onChange处理。 因此,状态随着输入的更改而更新。 form本身具有一个onSubmit处理函数,该处理函数调用formSubmit函数来处理您的API调用。 邮件的TextField具有一个onChange处理函数,该处理函数调用handleChangeEmail函数,该函数验证邮件TextField输入。
Now you need to add all the functions inside the Contact class component.
现在,您需要在Contact类组件中添加所有功能。
resetForm = () => { this.setState({ name: "", message: "", email: "", subject: "", buttonText: "Message Sent", }); setTimeout(() => { this.setState({ sent: false }); }, 3000); }; handleChangeEmail(e) { if ( !e.target.value.match( /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/ ) ) { this.setState({ email: e.target.value, }); this.setState({ emailError: true }); if (this.state.email === "") { // check if the input is empty this.setState({ emailError: false }); } } else { this.setState({ email: e.target.value, emailError: false }); } } formSubmit = async (e) => { e.preventDefault(); this.setState({ buttonText: "...sending", }); let data = { name: this.state.name, email: this.state.email, message: this.state.message, subject: this.state.subject, }; try { await axios.post("BACKEND_URL", data); this.setState({ sent: true }, this.resetForm()); } catch (error) { console.log(error); } };As the name suggests, The preventDefault() function (on line 36) prevents the form’s default action which would have triggered a page reload. When the message is being sent, the button text changes to “…Sending”, and Axios makes the API call. resetForm function will reset your form fields and update your button text. In the handleChangeEmail function validate the email address and update the state using the regular expression.
顾名思义, preventDefault() 功能 (在第36行) 防止表单的默认操作触发页面重新加载。 发送消息时,按钮文本变为“…正在发送”,并且Axios进行API调用。 resetForm 功能将重置您的表单字段并更新您的按钮文本。 在handleChangeEmail函数中,验证电子邮件地址并使用正则表达式更新状态。
Note: you need to update “BACKEND_URL” after you deploy the backend.
注意:部署后端后,您需要更新“ BACKEND_URL”。
Photo by Ferenc Almasi on Unsplash Ferenc Almasi在 Unsplash上 拍摄的照片Now you need to create a separate folder for the back-end development, I named the folder as “Form Backend”. You may use whatever name you prefer. To initialize the application run the following command in your shell/terminal in a specific folder (e.g., Form Backend)
现在您需要为后端开发创建一个单独的文件夹,我将该文件夹命名为“ Form Backend”。 您可以使用任何喜欢的名称。 要初始化应用程序,请在您的外壳程序/终端的特定文件夹(例如,Form Backend)中运行以下命令
// Initializenpm initYou need to set up the Express.js, nodemailer, config file, and route for that run the following command in your shell/terminal which was integrated with VSCode or your IDE.
您需要设置Express.js ,nodemailer,配置文件和路由,以便在与VSCode或IDE集成在一起的shell /终端中运行以下命令。
//Install express and other dependenciesnpm install express nodemailer cors --saveWe have installed CORS to allow cross-origin requests. In the package.json file, add the start property inside the existing scripts property. Your package.json scripts should like this:
我们已经安装了CORS以允许跨域请求。 在package.json文件中,在现有scripts属性内添加start属性。 您的package.json scripts应如下所示:
"scripts": { "start": "node ."}Now, in your directory you need to create an index.js file with the following code:
现在,在您的目录中,需要使用以下代码创建一个index.js文件:
const express = require("express"); const nodemailer = require("nodemailer"); const cors = require("cors"); const app = express(); const port = 4444; app.use(express.json()); app.use(express.urlencoded({ extended: false })); app.use(cors()); app.listen(process.env.PORT || port, () => { console.log("We are live on port 4444"); }); app.get("/", (req, res) => { res.send("Welcome to my mail api"); }); app.post("/api/v1", (req, res) => { let data = req.body; let smtpTransport = nodemailer.createTransport({ service: "WELL-KNOWN SERVICES", auth: { user: "USERNAME", pass: "PASSWORD", }, }); let mailOptions = { from: data.email, to: "ENTER_YOUR_EMAIL", subject: `${data.subject}`, html: `<p>${data.name}</p> <p>${data.email}</p> <p>${data.message}</p>`, }; smtpTransport.sendMail(mailOptions, (error, response) => { if (error) { res.send(error); } else { res.send("Success"); } smtpTransport.close(); }); });If you use a well-Known mail service then replace the “WELL-KNOWN SERVICES” with the service name listed in the link. Update your Email address and Password. We have set up a Nodemailer SMTP Transport and our route that will receive the data from our React form and send an email to the destination email address that we specify.
如果您使用知名的邮件服务,则用链接中列出的服务名称替换“知名服务”。 更新您的电子邮件地址和密码。 我们已经设置了一个Nodemailer SMTP传输和我们的路由,它将从React表单中接收数据并将电子邮件发送到我们指定的目标电子邮件地址。
hitesh choudhary from Pexels的 Pexels Hitesh Choudhary摄Before you push your code into GitHub make sure your backend repo is private because credentials will be exposed on GitHub.
在将代码推送到GitHub之前,请确保您的后端仓库是私有的,因为凭据将在GitHub上公开。
Push your front-end code to the corresponding repository. Deploy your front-end using Vercel. You could use any services but Vercel is easy to deploy. For the backend deployment, you could use Heroku. We couldn’t use Vercel to deploy backend because Express is not a good fit for the Vercel platform since it is primarily a Frontend-First company and provider Serverless Functions as lightweight helpers. Finally, be sure to copy the link and replace BACKEND_URL in the Contact.js file in the React app.
将您的前端代码推送到相应的存储库。 使用Vercel部署前端。 您可以使用任何服务,但Vercel易于部署。 对于后端部署,您可以使用Heroku 。 我们无法使用Vercel部署后端,因为Express不适用于Vercel平台,因为它主要是Frontend-First公司和轻量级帮助程序提供商Serverless Functions。 最后,确保复制链接并在React应用程序的Contact.js文件中替换BACKEND_URL。
Photo by SpaceX on Unsplash 由 SpaceX在 Unsplash上 拍摄Happy Coding 😎
快乐编码😎
翻译自: https://medium.com/design-bootcamp/serverless-material-ui-contact-form-55296e107609
相关资源:jdk-8u281-windows-x64.exe