我们将用Next.js和Netlify创建一个联系表,显示一个确认屏幕并具有增强的垃圾邮件检测功能。
Next.js是一个强大的React框架,用于开发可扩展的高性能React应用程序。通过整合Next.js网站和Netlify的技术,我们可以快速建立和运行一个有效的联系表,而不需要编写任何服务器端代码。
设置表单由Netlify处理不仅是一个相对快速的过程,而且还可以免费开始(在Netlify上托管的每个网站最多可免费提交100次)。提交的表单会自动通过Netlify内置的垃圾邮件过滤器,该过滤器使用Akismet,也有一些选项可以配置以提高垃圾邮件的检测水平。

创建联系表格
在Next.js应用程序中,我们应该创建一个ContactForm 组件来呈现联系页面中的联系表格。如果你想让这个表单呈现在/contact ,那么在pages/contact.js 文件中应该使用下面带有标签和输入字段的ContactForm 组件:
const ContactForm = (
<form
name="contact-form"
method="POST"
action="contact/?success=true"
>
<label htmlFor="name">Name *</label>
<input
id="name"
name="name"
required
type="text"
/>
<label htmlFor="company">Company *</label>
<input id="company" name="company" required type="text" />
<label htmlFor="email">E-mail Address *</label>
<input id="email" type="email" name="email" required />
<label htmlFor="message">Message *</label>
<textarea id="message" name="message" required></textarea>
<button type="submit">Submit</button>
</form>
);
上面的标记是用来呈现一个带有姓名、公司、电子邮件地址和信息字段的表单,并带有一个提交按钮。当提交表单时,根据表单的动作值,它应该从/contact 重定向到contact/?success=true 。现在,在有和没有成功查询参数的情况下,页面的外观还没有区别,但我们以后会更新。
到目前为止,我们的Contact.js 文件看起来是这样的:
import React from "react";
const ContactPage = () => {
const ContactForm = (/* code in above code sample*/)
return (
<div>
<h1>Contact Us</h1>
{ContactForm}
</div>
);
};
export default ContactPage;
现在我们已经建立了基本的表单,真正的神奇之处在于我们添加了额外的信息,以便Netlify在未来的网站部署中自动识别该表单。为了达到这个目的,我们应该更新表单的属性data-netlify="true" 和一个包含联系表单名称的隐藏输入域。在Netlify中,一旦我们在仪表板上导航到我们的网站,然后点击 "表单 "标签,我们就可以根据我们在隐藏字段中输入的名称来查看我们的表单响应。重要的是,如果你在一个网站内有多个表单,它们必须有唯一的名字,这样它们才能在Netlify中被正确记录。
<form
method="POST"
name="contact-form"
action="contact/?success=true"
data-netlify="true"
>
<input type="hidden" name="form-name" value="contact-form" />
在成功地将网站部署到Netlify的data-netlify 属性和form-name 字段后,我们就可以进入网站的部署版本并填写表单。在提交表格并导航到https://app.netlify.com/sites/site-name/forms (其中site-name 是您网站的名称)后,如果我们成功地设置了表格,那么我们最近提交的表格应该出现。

重定向到确认屏幕
为了改善用户体验,我们应该添加一些逻辑,当URL变为/contact/?success=true ,在表单提交时重定向到确认屏幕。也可以选择在表单提交时重定向到一个完全不同的页面作为动作,但使用查询参数,我们可以通过Next Router实现类似的目的。我们可以通过创建一个新的变量来实现这个目的,根据查询参数来决定是确认屏幕还是表单可见。与import { useRouter } from "next/router"; 一起导入的next/router可以用来检索当前的查询参数。
const router = useRouter();
const confirmationScreenVisible = router.query?.success && router.query.success === "true";
在我们的案例中,确认屏幕和表单不可能同时可见;因此,可以用下面的语句来确定表单是否可见:
const formVisible = !confirmationScreenVisible;
为了让用户可以选择重新提交表单,我们可以在确认屏幕上添加一个按钮,通过清除查询参数来重置表单。使用router.replace (而不是router.push )不仅可以更新页面,而且可以将历史中的当前页面替换为没有查询参数的版本:
<button onClick={() => router.replace("/contact", undefined, { shallow: true })}> Submit Another Response </button>
然后我们可以根据表单是否可见,有条件地渲染表单:
{formVisible ? ContactForm : ConfirmationMessage}
把这一切结合起来,我们可以使用下面的代码,根据查询参数(提交表单时更新)有条件地渲染表单:
import React, { useState } from "react";
import { useRouter } from "next/router";
const ContactPage = () => {
const [submitterName, setSubmitterName] = useState("");
const router = useRouter();
const confirmationScreenVisible =
router.query?.success && router.query.success === "true";
const formVisible = !confirmationScreenVisible;
const ConfirmationMessage = (
<React.Fragment>
<p>
Thank you for submitting this form. Someone should get back to you within 24-48 hours.
</p>
<button onClick={() => router.replace("/contact", undefined, { shallow: true })}> Submit Another Response </button>
</React.Fragment>
);
const ContactForm = (/* code in first code example */);
return (
<div>
<h1>Contact Us</h1>
{formVisible ? ContactForm : ConfirmationMessage}
</div>
);
};
export default ContactPage;
添加一个隐藏的机器人字段
现在我们的表单的核心功能已经工作了,除了基本的垃圾邮件检测,我们还可以为我们的表单添加额外的垃圾邮件检测,因为Akismet已经默认包含在所有Netlify表单中。我们可以通过添加data-netlify-honeypot="bot-field" 到我们的表单来启用这个功能:
<form
className="container"
method="POST"
name="contact-form"
action="contact/?success=true"
data-netlify="true"
data-netlify-honeypot="bot-field"
>
我们还需要创建一个新的隐藏段落,其中包含一个名为bot-field 的标签,其中包含输入。这个字段对机器人来说是 "可见 "的,但对人类来说不是。当这个蜜罐表单字段被填写时,Netlify会检测到一个机器人,然后提交被标记为垃圾邮件。
<p hidden>
<label>
Don’t fill this out: <input name="bot-field" />
</label>
</p>
进一步的定制
- 我们可以通过在Netlify表单中添加reCAPTCHA 2 来探索Netlify支持的另一个垃圾邮件预防选项。
- 我们可以更新表单以允许上传文件,输入
<input type="file">。 - 我们可以为表单提交设置通知。这发生在
https://app.netlify.com/sites/[your-site-name]/settings/forms,在那里我们可以包括一个自定义的主题字段(可以隐藏)用于电子邮件通知。

奖金
下面的代码包括我们所涉及的所有内容,以及用姓名字段中提交的内容设置自定义主题行的逻辑:
import React, { useState } from "react";
import { useRouter } from "next/router";
const ContactPage = () => {
const [submitterName, setSubmitterName] = useState("");
const router = useRouter();
const confirmationScreenVisible =
router.query?.success && router.query.success === "true";
const formVisible = !confirmationScreenVisible;
const ConfirmationMessage = (
<React.Fragment>
<p>
Thank you for submitting this form. Someone should get back to you
within 24-48 hours.
</p>
<button onClick={() => router.replace("/contact", undefined, { shallow: true })}> Submit Another Response </button>
</React.Fragment>
);
const ContactForm = (
<form
className="container"
method="POST"
name="contact-form"
action="contact/?success=true"
data-netlify="true"
data-netlify-honeypot="bot-field"
>
<input
type="hidden"
name="subject"
value={`You've got mail from ${submitterName}`}
/>
<input type="hidden" name="form-name" value="contact-form" />
<p hidden>
<label>
Don’t fill this out: <input name="bot-field" />
</label>
</p>
<label htmlFor="name">Name *</label>
<input
id="name"
name="name"
required
onChange={(e) => setSubmitterName(e.target.value)}
type="text"
/>
<label htmlFor="company">Company *</label>
<input id="company" name="company" required type="text" />
<label htmlFor="email">E-mail Address *</label>
<input id="email" type="email" name="email" required />
<label htmlFor="message">Message *</label>
<textarea id="message" name="message" required/>
<button type="submit">Submit</button>
</form>
);
return (
<div>
<h1>Contact Us</h1>
{formVisible ? ContactForm : ConfirmationMessage}
</div>
);
};
export default ContactPage;