signup.js에서 AppLayout로 일단 한번 감싸준다.
antd 자체에 Form태그가 있기 때문에 임포트 해준다.
알다시피 onFinish는 내부적으로 e.preventDefault가 자동으로 되기 때문에 따로 할 필요가 없다.
signup.js는 아래와 같이 해주고
// signup.js
import React, { useCallback, useState } from 'react';
import Head from 'next/head';
import { Form, Input } from 'antd';
import AppLayout from '../components/AppLayout';
const Signup = () => {
const [id, setId] = useState('');
const onChangeId = useCallback((e) => {
setId(e.target.value);
}, []);
const [nickname, setNickname] = useState('');
const onChangeNickname = useCallback((e) => {
setNickname(e.target.value);
}, []);
const [password, setPassword] = useState('');
const onChangePassword = useCallback((e) => {
setPassword(e.target.value);
}, []);
const onSubmit = useCallback(() => {
}, []);
return (
<AppLayout>
<Head>
<title>회원가입 | NodeBird</title>
</Head>
<Form onFinish={onSubmit}>
<div>
<label htmlFor="user-id">아이디</label>
<br />
<Input name="user-id" value={id} required onChange={onChangeId}/>
</div>
<div>
<label htmlFor="user-id">닉네임</label>
<br />
<Input name="user-id" value={nickname} required onChange={onChangeNickname}/>
</div>
<div>
<label htmlFor="user-id">비밀번호</label>
<br />
<Input name="user-password" type="password" value="{password}" required onChange={onChangePassword}/>
</div>
<div>
<label htmlFor="user-id">비밀번호체크</label>
<br />
<Input
name="user-password-check"
type="password"
value={passwordCheck}
required
onChange={onChangePasswordCheck}
/>
</div>
</Form>
</AppLayout>
);
};
export default Signup;
LoginForm에서도 보면 비슷하게 형태가 나와있다. state 하나 만들고 그거 바꾸는 callback만들고 하는 형태이다.
이러한 세트형태가 form에는 자주 보일것이다.
// LoginForm.js
const LoginForm = ({ setIsLoggedIn }) => {
const [id, setId] = useState('');
const onChangeId = useCallback((e) => {
setId(e.target.value);
}, []);
const [password, setPassword] = useState('');
const onChangePassword = useCallback((e) => {
setPassword(e.target.value);
}, [])
const style = useMemo(() => ({ marginTop: 10}), []);
const onSubmitForm = useCallback(() => {
console.log(id, password);
setIsLoggedIn(true);
}, [id, password]);
const LoginForm 부분을 커스텀으로 만들어보자. 훅을 쓸 수 있는 조건이 있는데 반복문이나 조건문 함수안에서는 안되고 컴포넌트 안에서만 되는데 유일한 예외가 커스텀 훅이다.
// LoginForm.js
const LoginForm = ({ setIsLoggedIn }) => {
// 이 부분부터
const [id, setId] = useState('');
const onChangeId = useCallback((e) => {
setId(e.target.value);
}, []);
const [password, setPassword] = useState('');
const onChangePassword = useCallback((e) => {
setPassword(e.target.value);
}, [])
const style = useMemo(() => ({ marginTop: 10}), []);
const onSubmitForm = useCallback(() => {
console.log(id, password);
setIsLoggedIn(true);
}, [id, password]);
hooks 폴더를 만들고 useInput.js 파일을 만들어서 작업을 하자. 평소에 중복을 제거하는 거 처럼 똑같이 만들어준다.
value setValue 리턴을 해주는데 useState와 useCallback을 합친거니까 return 부분에 value는 value, setValue 대신에 handler를 넣어준다. 이렇게 커스텀 훅으로 리턴해주면 둘이 합쳐져서 리턴이 된다.
// useInput.js
import { useState, useCallback } from 'react';
export default (initValue = null) => {
const [value, setValue] = useState(initValue);
const handler = useCallback((e) => {
setValue(e.target.value);
}, []);
return [value, handler];
}
다시 로그인 폼으로 가서 아래와 같이 줄일 수 있다. hooks들도 중복되면 중복을 제거할 수 있는 것이다.
// LoginForm.js
const LoginForm = ({ setIsLoggedIn }) => {
const [id, onChangeId] = useInput('');
const [password, onChangePassword] = useInput('');
const onChangePassword = useCallback((e) => {
setPassword(e.target.value);
}, [])
const onSubmitForm = useCallback(() => {
console.log(id, password);
setIsLoggedIn(true);
}, [id, password]);
signup파일에 와서 아래와 같이 바꿔준다. 여기서는 중복체크도 해줘야 하기 때문에 이 부분에서 차이가 난다.
// signup.js
const Signup = () => {
const [id, onChangeId] = useInput('');
const [nickname, onChangeNickname] = useInput('');
const [password, onChangePassword] = useInput('');
const onSubmit = useCallback(() => {
}, []);
이 부분을 useInput 커스텀 훅으로 줄일수도 있지만 하나 더 들어간다.
const [passwordCheck, setPasswordCheck] = useState('');
const onChangePasswordCheck = useCallback((e) => {
setPasswordCheck(e.target.value);
}, []);
패스워드 체크와 패스워드가 다른지를 확인하는 것이다. 이 부분이 달라서 얘는 커스텀 훅으로 합쳐주지를 못했다.
// signup.js
const onChangePasswordCheck = useCallback((e) => {
setPasswordCheck(e.target.value);
setPasswordError(e.target.value !== password);
}, [password]);
비밀번호랑 비밀번호 확인이 일치하는지 비밀번호 확인이 일치하지 않으면 passwordError 부분이 true가 될 것이다.
true가 되면 에러를 표시해주자.
// signup.js
const [id, onChangeId] = useInput('');
const [nickname, onChangeNickname] = useInput('');
const [password, onChangePassword] = useInput('');
const [passwordCheck, setPasswordCheck] = useState('');
const [passwordError, setPasswordError] = useState(false);
const onChangePasswordCheck = useCallback((e) => {
setPasswordCheck(e.target.value);
setPasswordError(e.target.value !== password);
}, [password]);
비밀번호 에러가 있으면 아래 문구가 나오게 하고 약관동의 체크박스가 나오게 한다.
// signup.js
import { Form, Input, Checkbox } from 'antd';
import styled from 'styled-components';
import AppLayout from '../components/AppLayout';
import useInput from '../hooks/useInput';
const ErrorMessage = styled.div`
color: red;
`
{passwordError && <Errormessage>비밀번호가 일치하지 않습니다.</Errormessage>}
<div>
<Checkbox name="user-term" checked={term} onChange={onChangeTerm}>제로초 말을 잘 들을 것을 동의합니다.</Checkbox>
{termError && <div style={{ color: 'red' }}>약관에 동의하셔야 합니다.</div>}
</div>
</Form>
</AppLayout>
);
};
// signup.js
const Signup = () => {
const [id, onChangeId] = useInput('');
const [nickname, onChangeNickname] = useInput('');
const [password, onChangePassword] = useInput('');
const [passwordCheck, setPasswordCheck] = useState('');
const [passwordError, setPasswordError] = useState(false);
const onChangePasswordCheck = useCallback((e) => {
setPasswordCheck(e.target.value);
setPasswordError(e.target.value !== password);
}, [password]);
const [term, setTerm] = useState('');
const [termError, setTermError] = useState(false);
const onChangeTerm = useCallback((e) => {
setTerm(e.target.checked);
setTermError(false);
}, []);
const onSubmit = useCallback(() => {
})
termError는 false인데 언제 true가 되냐 제출할때 true가 되게 제출버튼을 만든다.
{passwordError && <Errormessage>비밀번호가 일치하지 않습니다.</Errormessage>}
<div>
<Checkbox name="user-term" checked={term} onChange={onChangeTerm}>제로초 말을 잘 들을 것을 동의합니다.</Checkbox>
{termError && <ErrorMessage style={{ color: 'red' }}>약관에 동의하셔야 합니다.</ErrorMessage>}
</div>
</Form>
</AppLayout>
);
};
약관동의를 누르지 않았으면 에러가 뜨게 만든다. 그리고 사용자의 인풋 받는거를 여러번 체크를 하자.
const onSubmit = useCallback(() => {
if (password !== passwordCheck) {
return setPasswordError(true);
}
if (!term) {
return setTermError(true);
}
console.log(id, nickname, password)
}, [password, passwordCheck, term]);
const Signup = () => {
const [id, onChangeId] = useInput('');
const [nickname, onChangeNickname] = useInput('');
const [password, onChangePassword] = useInput('');
const [passwordCheck, setPasswordCheck] = useState('');
const [passwordError, setPasswordError] = useState(false);
const onChangePasswordCheck = useCallback((e) => {
setPasswordCheck(e.target.value);
setPasswordError(e.target.value !== password);
}, [password]);
const [term, setTerm] = useState('');
const [termError, setTermError] = useState(false);
const onChangeTerm = useCallback((e) => {
setTerm(e.target.checked);
setTermError(false);
}, []);
const onSubmit = useCallback(() => {
if (password !== passwordCheck) {
return setPasswordError(true);
}
if (!term) {
return setTermError(true);
}
console.log(id, nickname, password)
}, [password, passwordCheck, term]);
<출처 조현영: [리뉴얼] React로 NodeBird SNS 만들기>
[리뉴얼] React로 NodeBird SNS 만들기 - 인프런 | 강의
리액트 & 넥스트 & 리덕스 & 리덕스사가 & 익스프레스 스택으로 트위터와 유사한 SNS 서비스를 만들어봅니다. 끝으로 검색엔진 최적화 후 AWS에 배포합니다., 새로 만나는 제로초의 리액트 노드버
www.inflearn.com
'React > NodeBird(ZeroCho)' 카테고리의 다른 글
리덕스의 원리와 불변성 (0) | 2021.10.26 |
---|---|
redux설치 (0) | 2021.10.26 |
프로필 페이지 만들기 (0) | 2021.09.17 |
noreferrer&noopener (0) | 2021.09.17 |
더미 데이터로 로그인 (0) | 2021.09.17 |