pages/enter.tsx에 들어가서 useForm을 사용해주자
//pages/enter.tsx
interface EnterForm {
email?: string;
phone?: string;
}
...
const [submitting, setSubmitting] = useState(false);
const {register, handleSubmit, reset} = useForm<EnterForm>();
...
const onEmailClick = () => {
reset();
// email을 눌러서 데이터를 전송하고 또 phone을 눌러서 데이터를 전송하면
// 두 가지 데이터가 동시에 전송되므로 reset사용하여 하나만 전송시켜준다
setMethod("email")
};
const onPhoneClick = () => {
reset();
setMethod("phone")
};
...
const onValid = (validForm:EnterForm) => {
setSubmitting(true);
fetch("/api/users/enter", {
method: "POST",
body: JSON.stringify(data),
headers: {
"Content-Type": "application/json",
},
}).then(() => {
setSubmitting(false);
});
// POST 프로토콜로 JSON 인코딩된 데이터를 보내기 위해 fetch() 사용
// body의 데이터 유형은 반드시 "Content-Type"헤더와 일치해야 한다.
}
...
<form onSubmit={handleSubmit(onValid)} className="flex flex-col mt-8 space-y-4">
{method === "email" ? (
<Input
register = {register("email")}
name="email"
label="Email address"
type="email" required />
) : null} // Input은 미리 만드어둔 컴포넌트이다 깃헙 참고
{method === "phone" ? (
<Input
register = {register("phone")}
name="phone"
label="Phone number"
type="number"
kind="phone"
required
/>
) : null}
코드가 살짝 더럽지만 일단 저 상태로 냅둔다.
위와 같이 작성하면 클릭 버튼을 눌렀을 시 데이터가 url로 전송이된다.
// pages/api/users/enter.tsx
import { NextApiRequest, NextApiResponse } from "next";
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
if (req.method !== "POST") {
res.status(401).end();
}
console.log(req.body.email);
res.status(200).end();
}
해당 api url의 코드는 다음과 같다.
자주 쓰는 HTTP 상태 코드
200 OK: 요청이 성공적으로 되었습니다. (성공)
400 Bad Request: 이 응답은 잘못된 문법으로 인하여 서버가 요청을 이해할 수 없음을 의미합니다. (클라이언트에서 Request할 때 발생한 문제)
401 Unauthorized : 비록 HTTP 표준에서는 "미승인(unauthorized)"를 명확히 하고 있지만, 의미상 이 응답은 "비인증(unauthenticated)"을 의미합니다. 클라이언트는 요청한 응답을 받기 위해서는 반드시 스스로를 인증해야 합니다.
403 Forbidden: 클라이언트는 콘텐츠에 접근할 권리를 가지고 있지 않습니다. 401과 다른 점은 서버가 클라이언트가 누구인지 알고 있습니다.
405 Method Not Allowed: 요청한 메서드는 서버에서 알고 있지만, 제거되었고 사용할 수 없습니다. (허용되지 않은 메서드 사용)
500 Internal Server Error: 서버가 처리 방법을 모르는 상황이 발생했습니다. 서버는 아직 처리 방법을 알 수 없습니다.
useMutaion은 function과 state를 return하며 기존의 onValid함수 내에서 하던 일을 대신 해줄 것이다.
libs/client/useMutation.tsx를 생성해주자
import { useState } from "react"
interface UseMutationState {
loading: boolean;
data?: object;
error?: object;
}
type UseMutationResult = [(data: any) => void, UseMutationState];
export default function useMutation (url:string) :UseMutationResult {
const [state, setState] = useState<UseMutationState>({
loading: false,
data: undefined,
error: undefined,
});
function mutation(data: any) {
setState((prev) => ({ ...prev, loading: true }));
fetch(url, {
method: "POST",
body: JSON.stringify(data),
headers: {
"Content-Type": "application/json",
},
})
.then((response) => response.json().catch(() => {}))
.then((data) => setState((prev) => ({ ...prev, data })))
.catch((error) => setState((prev) => ({ ...prev, error })))
.finally(() => setState((prev) => ({ ...prev, loading: false })));
}
return [mutation, { ...state }];
}
기존 onValid랑 유사하다.
이후에 pages/enter.tsx는 간략하게 수정이 가능하다
const [enter,{loading, data, error}] = useMutation("/api/users/enter");
...
const onValid = (validForm:EnterForm) => {
enter(validForm)
}
handler는 프로토콜 요청을 return하기만 하고 POST냐 GET이냐 DELETE냐에 대한 것은 다른 컴포넌트에서 저장해줄것이다.
libs/server/withHandler.tsx를 만들어주자
import { NextApiRequest, NextApiResponse } from "next";
export default function withHandler(
method: "GET" | "POST" | "DELETE",
fn: (req: NextApiRequest, res: NextApiResponse) => void
) {
return async function (req: NextApiRequest, res: NextApiResponse) {
if (req.method !== method) {
return res.status(405).end();
}
try {
await fn(req, res);
} catch (error) {
console.log(error);
return res.status(500).json({ error });
}
};
}
이후 handler을 수정하면 다음과 같다.
import withHandler from "@libs/server/withHandler";
import { NextApiRequest, NextApiResponse } from "next";
import client from "../../../libs/client/client";
async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
console.log(req.body);
return res.status(200).end();
}
export default withHandler("POST", handler);
[NEXT] 당근마켓 (2-2) - 로그인 구현 (0) | 2023.02.10 |
---|---|
[NEXT]당근마켓(1) - Prisma를 이용한 Database 생성 (0) | 2023.02.08 |