commit bd878e4847802fb013b70a34b923a2206c2e4594
parent 345c460e6dccdf81e61982e8f869f73c8d025985
Author: Yongbin Kim <iam@yongbin.kim>
Date: Mon, 30 Jan 2023 12:05:57 +0900
fix: 회원가입 폼 제대로 동작하지 않던 문제 수정
Signed-off-by: Yongbin Kim <iam@yongbin.kim>
Diffstat:
3 files changed, 56 insertions(+), 88 deletions(-)
diff --git a/lib/hooks/use_form.ts b/lib/hooks/use_form.ts
@@ -49,6 +49,7 @@ export const useForm = <T extends FormFields, Result = unknown> (
input: string | { method: string, url: string | URL },
initial: T,
onSuccess?: (result: Result) => void,
+ onError?: (status: number, error: ApiError) => void,
): [fields: T, updateFields: UpdateFieldOrDispatch<T>, submit: () => void,
isLoading: boolean, result: Result | null, error: ApiError | null] => {
const [fields, updateFields] = useFields<T>(initial)
@@ -79,6 +80,7 @@ export const useForm = <T extends FormFields, Result = unknown> (
if (!res.ok) {
setError(data)
+ onError?.(res.status, data)
return
}
diff --git a/pages/users/signup/[id].tsx b/pages/users/signup/[id].tsx
@@ -7,6 +7,7 @@ import Container from '@/components/layout/Container'
import Hero from '@/components/layout/Hero'
import Section from '@/components/layout/Section'
import { isApiError } from '@/lib/apierror'
+import { useForm } from '@/lib/hooks/use_form'
import { getUnconfirmedSignupRequest } from '@/lib/models/signup_request'
import { GetServerSideProps } from 'next'
import { useRouter } from 'next/router'
@@ -46,28 +47,23 @@ export default function SignUpCompletePage (props: PageProps) {
const router = useRouter()
const requestId = router.query.id as string
- const [password, setPassword] = useState('')
- const [passwordError, setPasswordError] = useState<string | null>(null)
const [passwordRepeat, setPasswordRepeat] = useState('')
+
+ const [passwordError, setPasswordError] = useState<string | null>(null)
const [passwordRepeatError, setPasswordRepeatError] = useState<string | null>(null)
- const [nickname, setNickname] = useState('')
const [nicknameError, setNicknameError] = useState<string | null>(null)
- const [isLoading, setLoading] = useState(false)
- // 비밀번호 확인 오류 표시
- useEffect(() => {
- if (passwordRepeat?.length === 0) {
- return
- }
- setPasswordRepeatError(
- password !== passwordRepeat
- ? 'password-unmatched'
- : null,
- )
- }, [password, passwordRepeat])
-
- const handleSubmit = useCallback(() => {
- const handleError = (status: number, err: any) => {
+ const [fields, updateFields, submit, isLoading] = useForm(
+ { method: 'POST', url: `/api/users/signup/${requestId}` },
+ {
+ password: '',
+ nickname: '',
+ },
+ () => {
+ router.push('/users/login')
+ .catch(console.error)
+ },
+ (status, err) => {
if (!isApiError(err)) {
setPasswordError('알 수 없는 오류가 발생했습니다.')
return
@@ -97,43 +93,23 @@ export default function SignUpCompletePage (props: PageProps) {
setPasswordError('알 수 없는 오류가 발생했습니다.')
}
+ )
- setLoading(false)
- setPasswordError(null)
- setNicknameError(null)
- if (password !== passwordRepeat) {
- setPasswordRepeatError('비밀번호가 일치하지 않습니다.')
+ // 비밀번호 확인 오류 표시
+ useEffect(() => {
+ if (passwordRepeat?.length === 0) {
return
}
-
- !(async () => {
- const res = await fetch(`/api/users/signup/${requestId}`, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify({
- password,
- nickname,
- }),
- })
-
- if (res.ok) {
- await router.push('/users/login')
- return
- }
-
- const err = await res.json()
- handleError(res.status, err)
- })().catch((err) => {
- console.error(err)
- setPasswordError('알 수 없는 오류가 발생했습니다.')
- })
- }, [])
+ setPasswordRepeatError(
+ fields.password !== passwordRepeat
+ ? '비밀번호가 일치하지 않습니다.'
+ : null,
+ )
+ }, [fields.password, passwordRepeat])
return (
- <Form onSubmit={handleSubmit}>
+ <Form onSubmit={submit}>
<Hero>
<Title kind="headline">Sign up</Title>
</Hero>
@@ -144,20 +120,23 @@ export default function SignUpCompletePage (props: PageProps) {
<Field
type="text"
placeholder="Email"
+ disabled={isLoading}
readOnly
value={props.email}
/>
<Field
type="password"
placeholder="Password"
+ disabled={isLoading}
color={passwordError ? 'error' : undefined}
message={passwordError ?? undefined}
- value={password}
- onValueChange={setPassword}
+ value={fields.password}
+ onValueChange={updateFields.bind(null, 'password')}
/>
<Field
type="password"
placeholder="Password (Repeat)"
+ disabled={isLoading}
color={passwordRepeatError ? 'error' : undefined}
message={passwordRepeatError ?? undefined}
value={passwordRepeat}
@@ -166,17 +145,18 @@ export default function SignUpCompletePage (props: PageProps) {
<Field
type="text"
placeholder="Nickname"
+ disabled={isLoading}
color={nicknameError ? 'error' : undefined}
message={nicknameError ?? undefined}
- value={nickname}
- onValueChange={setNickname}
+ value={fields.nickname}
+ onValueChange={updateFields.bind(null, 'nickname')}
/>
</Fields>
<SubmitButton
color="primary"
disabled={isLoading}
- value={'Sign up'}
+ value="Sign up"
/>
</Section>
</Container>
diff --git a/pages/users/signup/index.tsx b/pages/users/signup/index.tsx
@@ -6,8 +6,13 @@ import Form from '@/components/form/Form'
import Container from '@/components/layout/Container'
import Hero from '@/components/layout/Hero'
import Section from '@/components/layout/Section'
+import { useForm } from '@/lib/hooks/use_form'
import { useRouter } from 'next/router'
-import { useCallback, useState } from 'react'
+import { useState } from 'react'
+
+interface SignUpFormFields {
+ email: string
+}
export default function SignUpPage () {
return (
@@ -27,12 +32,14 @@ export default function SignUpPage () {
function SignUpForm () {
const router = useRouter()
- const [email, setEmail] = useState('')
- const [isLoading, setLoading] = useState(false)
- const [errorMessage, setErrorMessage] = useState<string | null>(null)
-
- const handleSubmit = useCallback(() => {
- const handleError = (status: number) => {
+ const [fields, updateFields, submit, isLoading] = useForm<SignUpFormFields>(
+ { method: 'POST', url: '/api/users/signup' },
+ { email: '' },
+ () => {
+ router.push('/users/signup/sent')
+ .catch(console.error)
+ },
+ (status) => {
switch (status) {
case 401:
setErrorMessage('이메일 혹은 비밀번호가 잘못되었습니다.')
@@ -42,42 +49,21 @@ function SignUpForm () {
setErrorMessage('알 수 없는 오류가 발생했습니다.')
break
}
- }
-
- setLoading(true)
- setErrorMessage(null)
-
- !(async () => {
- const res = await fetch('/api/users/signup', {
- method: 'POST',
- body: JSON.stringify({ email }),
- })
-
- if (!res.ok) {
- handleError(res.status)
- setLoading(false)
- return
- }
-
- await router.push('/users/signup/sent')
- })().catch((err) => {
- console.error(err)
- setErrorMessage('알 수 없는 오류가 발생했습니다.')
- setLoading(false)
- })
- }, [router, email])
+ },
+ )
+ const [errorMessage, setErrorMessage] = useState<string | null>(null)
return (
- <Form onSubmit={handleSubmit}>
+ <Form onSubmit={submit}>
<Fields>
<Field
type="text"
disabled={isLoading}
placeholder="Email"
color={errorMessage == null ? undefined : 'error'}
- value={email}
+ value={fields.email}
message={errorMessage ?? undefined}
- onValueChange={setEmail}
+ onValueChange={updateFields.bind(null, 'email')}
/>
</Fields>