프로젝트는 현재 코인고스트 앱 페이지에서 실제로 사용되고 있는, 블로고의 리스트페이지, 상세페이지 그리고 회원가입 페이지를 구현하는 것이다.
프로젝트 github 주소
NextJS ,React Hook ,typescript, Styled Components, SWR, Recoil
체크박스
회원가입
체크박스는 모두 동의 클릭 시에 필수만 체크가 되어지게 구현을 했다.
//index.txs
const [checkedItems, setCheckedItems] = useState<any>(new Set());
const [isAllChecked, setIsAllChecked] = useState(false);
const checkId = new Set(checkedItems)
const checkedItemHandler = (id: number) => {
if (!checkedItems.has(id)) {
checkId.add(id);
setCheckedItems(checkId);
} else if (checkedItems.has(id)) {
checkId.delete(id);
setCheckedItems(checkId);
}
if(checkId.size===3){
setIsAllChecked(true)
}
};
const allCheckedHandler = (isChecked : boolean) => {
if (isChecked) {
setCheckedItems(new Set(signUpData.map(({ id }) => id)));
setIsAllChecked(true);
} else {
checkId.clear();
setIsAllChecked(false);
setCheckedItems(checkId)
}
};
new Set을 사용하여 생각보다 쉽게 구현 할 수 있었으며, new Set 사용법에 대해서 익숙해졌다.
먼저 전체 선택 관리를 하는 allCheckedHandler 함수를 보자. 일단 불변성을 유지하기 위해서 checkId라는 변수를 사용하였다. (signUpData는 map을 돌리기 위한 상수 데이터)
전체 선택하는 components로 넘겨 체크 상태를 boolean 값으로 받아 true일 경우 checkedItems에 상수 데이터의 모든 id값을 넣어주고 isAllChecked를 true로 바뀌어 전체 선택이 되어지게 구현, 반대일 경우는 clear()다 지워주고 isAllChecked를 false로 바꾸었다.
//AllCheck.tsx
const [bChecked, setChecked] = useState(false);
const checkHandler = () => {
setChecked(!bChecked);
onClickHandler(!bChecked);
};
그 다음 하나하나 체크를 위한 checkedItemHandler함수를 보면 id로 체크를 해서 없으면 add, 있으면 delete하여 체크를 하였고, size가(length)3이면 올체크가 되어지게 구현!
//EssentialCheck.tsx
const [bChecked, setChecked] = useState(false);
const checkHandler = () => {
setChecked(!bChecked);
onClickItemHandler(el.id);
};
const allCheckHandler = () => setChecked(isAllChecked);
useEffect(() => allCheckHandler(), [isAllChecked]);
isAllChecked를 props로 넘겨 전체 체크 선택 시에도 작동이 되어지게 해야했음(useEffect사용)
회원가입 페이지는 react-hook-form 라이브러리 사용하여 어렵지 않게 구현하여, API를 이용해서 인증번호 받아 인증번호 인증하는 POST요청 부분을 써보려고 한다.
//Register.tsx
const postRegister = () => {
const postPhone = {
phone: watch('phone'),
};
fetch('/api/register', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(postPhone),
})
.then((res) => res.json())
.then((data) => alert(data?.data.message));
};
postPhone변수를 만들어 핸드폰번호 인풋에 담겨져 있는 번호를 가져와 바디에 실어 post요청을 보낸다. post요청은 wecode 프로젝트에서도 맡아 본 적이 없어 처음에 headers를 계속 안쓰고 요청을 보냈다가 시간을 많이 잡아 먹었다.
찾아보니 Content-Type에 따라서 client에서 server로 보내는 데이터의 형식이 달라진다고 한다. json으로 보내야하니 application/json이라고 작성!
//Register.tsx
const postAuth = () => {
const postPhone = {
auth: watch('auth'),
};
fetch('/api/auth', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(postPhone),
})
.then((res) => res.json())
.then((data) => {
if(data.data.message === true){
setAuthData(data.data.message)
alert('인증 성공')
}else{
alert(data.data.message);
}
});
};
인증번호 부분도 마찬가지로 똑같이 구현했다. 핸드폰 인증에서 받은 번호를 입력하면 message로 true가 오면 '인증 성공' 실패 시에는 에러 메세지를 띄워준다.