반응형
Next.js 및 Netlify와 함께 확인 화면을 표시하고 향상된 스팸 탐지 기능을 갖춘 연락처 양식을 만들 예정입니다.
Next.js는 확장 가능한 고성능 리액트 애플리케이션을 개발하기 위한 강력한 리액트 프레임워크입니다. Next.js 사이트를 Netlify의 기술과 통합함으로써 서버 쪽 코드를 작성할 필요 없이 작업 중인 연락처 양식을 빠르게 만들어 실행할 수 있습니다.
Netlify에서 처리할 양식을 설정하는 것은 비교적 빠른 프로세스일 뿐만 아니라, Netlify에서 호스팅되는 사이트당 최대 100개의 무료 제출/개까지 자유롭게 시작할 수 있습니다. 양식 제출은 Akismet을 사용하는 Netlify의 내장된 스팸 필터를 통해 자동으로 처리되며 스팸 탐지 수준을 높이도록 구성할 수 있는 옵션도 있습니다.
연락처 양식 작성
Within the Next.js application we should create a `ContactForm` component to render the contact form inside of the contact page. If you’d like for this form to render at `/contact`, then the `ContactForm` component below with labels and input fields should be used within the `pages/contact.js` file.
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>
);
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>
);
The above markup is required to render a form with a field for Name, Company, Email address and message with a submit button. When submitting the form, based on the value of the form’s action, it should redirect to `contact/?success=true` from `/contact`. Right now there is not yet a difference between the page’s appearance with and without the success query parameter, but we will update that later.
Our `Contact.js` file looks like this so far:
import React from "react";
const ContactPage = () => {
const ContactForm = (/* code in above code sample*/)
return (
<div>
<h1>Contact Us</h1>
{ContactForm}
</div>
);
};
export default ContactPage;
import React from "react";
const ContactPage = () => {
const ContactForm = (/* code in above code sample*/)
return (
<div>
<h1>Contact Us</h1>
{ContactForm}
</div>
);
};
export default ContactPage;
Now that we have the basic form set up, the real magic will happen after we add additional information for Netlify to auto-recognize the form during future site deployments. To accomplish this we should update the form to have the attribute `data-netlify="true"` and a hidden input field that contains the name of our contact form. In Netlify, once we navigate to our site in the dashboard and then click on the “forms” tab we will be able to view our form responses based on the name that we’ve put in our hidden field. It’s important that if you have multiple forms within a site that they have unique names so that they are recorded properly in Netlify.
<form
method="POST"
name="contact-form"
action="contact/?success=true"
data-netlify="true"
>
<input type="hidden" name="form-name" value="contact-form" />
```
```js
<form
method="POST"
name="contact-form"
action="contact/?success=true"
data-netlify="true"
>
<input type="hidden" name="form-name" value="contact-form" />
```
<div class="content-ad"></div>
```js
After successfully deploying the site to Netlify with the `data-netlify` attribute and the `form-name` field then we can go to the deployed version of the site and fill out the form. Upon submitting the form and navigating to `https://app.netlify.com/sites/site-name/forms` (where `site-name` is the name of your site) then our most recent form submission should appear if we have successfully set up the form.
```
![image](https://i1.wp.com/css-tricks.com/wp-content/uploads/2021/10/Screen-Shot-2021-09-19-at-7.42.08-PM.png?resize=2048%2C1144&ssl=1)
### 확인 화면으로 리디렉션
```js
In order to improve the user experience, we should add some logic to redirect to a confirmation screen on form submission when the URL changes to `/contact/?success=true`. There is also the option to redirect to an entirely different page as the action when the form is submitted but using query params we can achieve something similar with the Next Router. We can accomplish this by creating a new variable to determine if the confirmation screen or the form should be visible based on the query parameter. The next/router which is imported with `import { useRouter } from "next/router";` can be used to retrieve the current query params.
```
```js
const router = useRouter();
const confirmationScreenVisible = router.query?.success && router.query.success === "true";
```
<div class="content-ad"></div>
```js
const router = useRouter();
const confirmationScreenVisible = router.query?.success && router.query.success === "true";
```
우리의 경우 확인 화면과 양식을 동시에 볼 수 없기 때문에 다음의 문구를 사용하여 양식이 보이는지 확인할 수 있습니다.
```js
const formVisible = !confirmationScreenVisible;
```
```js
const formVisible = !confirmationScreenVisible;
```
```js
To give users the option to resubmit the form, we can add a button to the confirmation screen to reset the form by clearing the query params. Using `router.replace` (instead of `router.push`) not only updates the page but replaces the current page in the history to the version without query params.
```
<div class="content-ad"></div>
```js
<button onClick={() => router.replace("/contact", undefined, { shallow: true })}> Submit Another Response </button>
```
```js
<button onClick={() => router.replace("/contact", undefined, { shallow: true })}> Submit Another Response </button>
```
그런 다음 폼의 표시 여부에 따라 조건부로 폼을 렌더링할 수 있습니다.
```js
{formVisible ? ContactForm : ConfirmationMessage}
```
```js
{formVisible ? ContactForm : ConfirmationMessage}
```
<div class="content-ad"></div>
이 모든 것을 종합하면, 다음 코드를 사용하여 쿼리 매개 변수(양식이 제출될 때 업데이트됨)에 따라 조건부로 양식을 렌더링할 수 있습니다.
```js
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;
```
```js
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;
```
### 숨김 봇 필드 추가
```js
Now that the core functionality of our form is working, we can add additional spam detection to our form in addition to the base spam detection because Akismet is included with all Netlify Forms by default. We can enable this by adding `data-netlify-honeypot="bot-field"` to our form.
```
<div class="content-ad"></div>
```js
<form
className="container"
method="POST"
name="contact-form"
action="contact/?success=true"
data-netlify="true"
data-netlify-honeypot="bot-field"
>
```
```js
<form
className="container"
method="POST"
name="contact-form"
action="contact/?success=true"
data-netlify="true"
data-netlify-honeypot="bot-field"
>
```
```js
We also need to create a new hidden paragraph that contains a label named `bot-field` that contains the input. This field is “visible” to bots, but not humans. When this honeypot form field is filled, Netlify detects a bot and then the submission is flagged as spam.
```
```html
<p hidden>
<label>
Don’t fill this out: <input name="bot-field" />
</label>
</p>
```
```js
<p hidden>
<label>
Don’t fill this out: <input name="bot-field" />
</label>
</p>
```
<div class="content-ad"></div>
### 추가 사용자 지정
- 우리는 Netliify 양식에 reCAPTCHA 2를 추가하여 Netlify가 지원하는 또 다른 스팸 차단 옵션을 살펴볼 수 있습니다.
- `<input type="file">` 입력으로 업로드된 파일을 허용하도록 양식을 업데이트할 수 있습니다.
- 양식 제출에 대한 알림을 설정할 수 있습니다. 이메일 알림에 사용자 지정 제목 필드(숨길 수 있음)를 포함시킬 수 있는 `https://app.netlify.com/sites/[your-site-name]/site/forms]에서 이러한 작업이 발생합니다.
![image](https://i0.wp.com/css-tricks.com/wp-content/uploads/2021/10/Screen-Shot-2021-09-19-at-7.43.14-PM.png?resize=1972%2C1198&ssl=1)
### 전체 코드
전체 사이트 코드는 GitHub에서 확인할 수 있습니다.
<div class="content-ad"></div>
### 보너스
다음 코드에는 이름 필드에 제출된 내용으로 사용자 지정 제목 줄을 설정하는 논리는 물론 우리가 다룬 모든 내용이 포함되어 있습니다.
```js
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;
```
```js
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;
```
'css' 카테고리의 다른 글
어쩌면 아무것도 아닐지도 모른다 (0) | 2021.12.29 |
---|---|
기계 학습에 대한 시각적 소개 (0) | 2021.12.29 |
CSS-in-React 풍경 (0) | 2021.10.25 |
Visual Studio Code를 브라우저 내 개발자 도구 편집기로 사용할 수 있다면 어떨까요? (0) | 2021.10.25 |
CSS 페인트 API 탐색: 원형 모양 (0) | 2021.10.25 |
댓글