-
Notifications
You must be signed in to change notification settings - Fork 41
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
회원가입 로직 기능을 추가합니다. #139
회원가입 로직 기능을 추가합니다. #139
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { http } from "../../../lib/http"; | ||
import { UserSchema } from "../_types"; | ||
import type { UserType, RegisterReq, UserErrorType } from "../_types"; | ||
|
||
export function register(req: RegisterReq): Promise<UserType | UserErrorType | undefined> { | ||
return http.post({ | ||
url: "/users", | ||
body: { | ||
user: req, | ||
}, | ||
schema: UserSchema, | ||
}); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
interface ErrorMessageProps { | ||
message?: string; | ||
} | ||
|
||
export function ErrorMessage({ message }: ErrorMessageProps): JSX.Element { | ||
return ( | ||
<ul className="error-messages"> | ||
<li>{message}</li> | ||
</ul> | ||
); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
"use client"; | ||
|
||
import type { SubmitHandler } from "react-hook-form"; | ||
import { useForm } from "react-hook-form"; | ||
import { useRouter } from "next/navigation"; | ||
import type { RegisterReq } from "../_types"; | ||
import { useRegister } from "../_hooks/use-register"; | ||
import { UserSchema, UserType } from "../_types"; | ||
import { ErrorMessage } from "./error-message"; | ||
|
||
export function RegisterForm(): JSX.Element { | ||
const { | ||
register, | ||
handleSubmit, | ||
formState: { errors }, | ||
setError, | ||
resetField, | ||
} = useForm<RegisterReq>(); | ||
|
||
const { mutate } = useRegister(); | ||
|
||
const router = useRouter(); | ||
|
||
const onSubmit: SubmitHandler<RegisterReq> = data => { | ||
mutate(data, { | ||
onSuccess: () => { | ||
router.push("/login"); | ||
}, | ||
onError: () => { | ||
setError("email", { | ||
message: "email has already been taken", | ||
}); | ||
setError("username", { | ||
message: "username has already been taken", | ||
}); | ||
|
||
resetField("password"); | ||
}, | ||
}); | ||
}; | ||
|
||
const isEmailValid = (email: string) => { | ||
const emailPattern = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i; | ||
return emailPattern.test(email); | ||
}; | ||
|
||
return ( | ||
// eslint-disable-next-line @typescript-eslint/no-misused-promises | ||
<form onSubmit={handleSubmit(onSubmit)}> | ||
<fieldset className="form-group"> | ||
<input | ||
{...register("username", { required: "Username can't be blank" })} | ||
className="form-control form-control-lg" | ||
placeholder="Username" | ||
type="text" | ||
/> | ||
</fieldset> | ||
{errors.username ? <ErrorMessage message={errors.username.message} /> : null} | ||
Comment on lines
+50
to
+58
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. react-hook-form 다룰 때 필연적으로 JSX 부분이 길어지게 되는데 하나의 훅으로 분리하는 것도 좋더라구요. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. react-hook-form의 validation쪽은 zod와 엮어서 다뤄봐도 좋을 것 같아요~ |
||
|
||
<fieldset className="form-group"> | ||
<input | ||
{...register("email", { | ||
required: "Email can't be blank", | ||
validate: email => isEmailValid(email) || "Invalid email format", | ||
})} | ||
className="form-control form-control-lg" | ||
placeholder="Email" | ||
type="text" | ||
/> | ||
</fieldset> | ||
{errors.email ? <ErrorMessage message={errors.email.message} /> : null} | ||
|
||
<fieldset className="form-group"> | ||
<input | ||
{...register("password", { required: "Password can't be blank" })} | ||
className="form-control form-control-lg" | ||
placeholder="Password" | ||
type="password" | ||
/> | ||
</fieldset> | ||
{errors.password ? <ErrorMessage message={errors.password.message} /> : null} | ||
|
||
<button className="btn btn-lg btn-primary pull-xs-right" type="submit"> | ||
Sign up | ||
</button> | ||
</form> | ||
); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import { useMutation } from "@tanstack/react-query"; | ||
import type { RegisterReq } from "../_types"; | ||
import { register } from "../_api"; | ||
|
||
export function useRegister() { | ||
return useMutation({ | ||
mutationFn: (req: RegisterReq) => register(req), | ||
}); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import { z } from "zod"; | ||
|
||
export interface RegisterReq { | ||
username: string; | ||
email: string; | ||
password: string; | ||
} | ||
|
||
export const UserErrorsSchema = z.object({ | ||
errors: z.object({ | ||
email: z.array(z.string()), | ||
username: z.array(z.string()), | ||
}), | ||
}); | ||
|
||
export const UserSchema = z.object({ | ||
user: z.object({ | ||
email: z.string(), | ||
token: z.string(), | ||
username: z.string(), | ||
bio: z.string(), | ||
image: z.string(), | ||
}), | ||
}); | ||
|
||
export type UserErrorType = z.infer<typeof UserErrorsSchema>; | ||
|
||
export type UserType = z.infer<typeof UserSchema>; |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
요렇게 하는것도 좋을 것 같아요! 일부러 분리시킨 걸까요?