-
Notifications
You must be signed in to change notification settings - Fork 0
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
[ 4주차 기본/심화/생각 과제 ] 🍁 로그인/회원가입 #4
base: main
Are you sure you want to change the base?
Conversation
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.
이번 과제 혠언니한테 너무나도 많은 도움을 받았따.... 언니 없었으면 나 과제 제출 못했을거야🫶
너무너무 고맙고 과제하느라 고생해따!!!!
<UserInform inform="ID" text={userData.nickname} /> | ||
<UserInform inform="닉네임" text={userData.username} /> |
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.
타임 타임 이거 받아오는 값 바뀐거 아닌가요?!?!?!? ID에 username이고 닉네임에 nickname 아닌가?!
import { Link } from "react-router-dom"; | ||
|
||
export default function LogoutBtn() { | ||
return <LogoutButton to="/login">Logout</LogoutButton>; |
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.
useNavigate만 썼는데 안쓰고도 이게 가능하구나!
const isExistData = response.data.isExist; | ||
if (isExistData) { | ||
setIsExist(true); | ||
} else if (!isExistData) { | ||
setIsExist(false); | ||
} |
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.
나는 그냥 바로 response.data.isExist
를 조건문에 넣어줬는데 요렇게 따로 빼주는게 훨신 깔끔한거 같다!
그리고 조건문 쓸 때 나도 if, else if 로 해주긴 했는데 왜 else로 했을 땐 제대로 동작을 하지 않을까....? if-else는 안되고 if-else if는 또 되더라고.. 아직도 이유를 모르겠어 ..
useEffect(() => { | ||
setIsExist(0); | ||
}, [value]); |
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.
요기로 중복체크 버튼 클릭했다가도 input 값이 수정되면 다시 검정색으로 되돌아가게 하는 코드 맞지?!
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.
Flag가 무슨 역할을 하는지 궁금해!
console.log("성공"); | ||
return response; | ||
} catch (error) { | ||
console.error("로그인 실패", error.message); |
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.
error.message
는 API로 주어졌던 메시지가 출력되는건가?!
여기서 console.error 처음 알아가..!
[정리] console.log와 console.error는 모두 console에 출력하는 거지만, console.log는 stdout, console.error는 stderr에 해당한다..!
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.
엥 나도 좋은 정보 감사합니다!
const reducer = (state, action) => { | ||
switch (action.type) { | ||
case "SET_ID": | ||
return { ...state, idValue: action.payload }; | ||
case "SET_PW": | ||
return { ...state, pwValue: action.payload }; | ||
case "SET_PW_CHECK": | ||
return { ...state, pwCheckValue: action.payload }; | ||
case "SET_NAME": | ||
return { ...state, nameValue: action.payload }; | ||
case "SET_EXIST": | ||
return { ...state, isExist: action.payload }; | ||
case "SET_PW_VALID": | ||
return { ...state, isPwValid: action.payload }; | ||
case "SET_DISABLED": | ||
return { ...state, disabled: action.payload }; | ||
default: | ||
return state; | ||
} | ||
}; |
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.
이거 좀 좋은거 같다.. 난 아직 useReducer 쓰는게 익숙하지 않아서 좀 더 공부를 해보도록 할게.. payload도 여기서 처음 봤어! 리팩토링 할 때 언니 코드 참고해야지 히히
payload
: 보내고자 하는 데이터를 의미 (혹시 이게 아니라면 고쳐서 알려주면 고마울거 가타..🫶)
const pwConfirm = useCallback(() => { | ||
if ( | ||
!state.pwValue || | ||
!state.pwCheckValue || | ||
state.pwValue != state.pwCheckValue | ||
) { | ||
dispatch({ type: "SET_PW_VALID", payload: false }); | ||
} else if ( | ||
state.pwValue && | ||
state.pwCheckValue && | ||
state.pwValue == state.pwCheckValue | ||
) { | ||
dispatch({ type: "SET_PW_VALID", payload: true }); | ||
} | ||
}, [state.pwValue, state.pwValue, state.pwCheckValue]); |
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.
여기 useCallback
을 쓴 이유가 deps안에 있는 값들이 변경됐을 때 함수를 다시 실행하도록 하려 한건가..?
근데 왜 deps 안에 state.pwValue
가 두개야?! 저 두개가 서로 다른건가?
useEffect(() => { | ||
pwConfirm(); | ||
}, [pwConfirm]); |
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.
위에서 pwConfirm()
을 만들고 useEffect에 넣어주는거랑, 바로 pwConfirm
에 useEffect를 적용하는거랑 다른 점이 있나?
저 위의 함수에 useEffect
가 아니라 useCallback
을 적용한 이유가 따로 있는지 알고싶어!
const trimmedId = state.idValue.trim(); | ||
const trimmedPw = state.pwValue.trim(); | ||
const trimmedName = state.nameValue.trim(); |
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.
헉...... 공백이 있을수도 있구나.... 별 생각 없이 그냥 입력된 값을 그대로 넘겨줬는데 앞뒤로 공백을 제거해서 넘겨주는게 좀 더 좋을거 같다..! 나도 적용해볼게 ㅎㅎ
String.tirm()
: 문자열 앞 뒤의 공백을 제거해줌
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.
과제하느라 고생했어 🖤 컴포넌트가 잘 분리되어 있어서 보기 좋았어!!
try { | ||
const response = await axios.get( | ||
`${import.meta.env.VITE_APP_BASE_URL}/api/v1/members/${userId}`, | ||
{ | ||
userId: userId, | ||
} | ||
); | ||
const { data } = response; | ||
setUserData(data); |
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.
요기 data로 바로 선언했으면 바로 값넣을 수 있었을텐데 가독성을 위해서인가용?
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.
signup이랑 login 컴포넌트가 비슷해서 재사용 하는 방벙으로 했어도 좋을것 같아!
onChange={(e) => | ||
dispatch({ type: "SET_ID", payload: e.target.value }) | ||
} | ||
title="ID" |
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.
접근성 때문에 넣은거 맞지?! input에는 title 속성으로 주는구낭 배워가요 !
export const placeholder = { | ||
ID_HOLDER: "아이디를 입력해주세요", | ||
PW_HOLDER: "비밀번호를 입력해주세요", | ||
PW_COMFIRM_HOLDER: "비밀번호를 다시 한 번 입력해주세요", | ||
NICKNAME_HOLDER: "닉네임을 입력해주세요", | ||
}; |
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.
상수화 깔끔하다!! 좋아요 🖤
<Header>Sign Up</Header> | ||
<div> | ||
<IdInputBox | ||
isExist={state.isExist} |
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.
styled componenet에 prop넘겨줄 때 warning 안떴오?!
나는 앞에 $를 붙이라는 경고가 뜨더라구
} catch (ex) { | ||
if (ex.response.status === 400) { | ||
console.log("비밀번호로 인한 로그인실패!"); | ||
setShowModal(true); | ||
setModalMessage(ex.response.data.message); | ||
} else { | ||
console.log("axios 에러"); |
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.
이거 response.data.message 에 에러가 담겨서 나와!
등록되지 않은 유저 라는 메세지도 있어서 이걸로 받아줘야 할 것 같아용!!
<ThemeProvider theme={theme}> | ||
<GlobalStyle /> | ||
<Router /> | ||
<Flag /> |
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.
요건 왜 있는걸까?
|
||
export default function LoginBtn({ onClick }) { | ||
return <LoginButton onClick={onClick}>로그인</LoginButton>; | ||
} | ||
|
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.
회원가입이랑 로그인버튼을 따로 만들어줬구나!
export default function Modal({ children }) { | ||
return ( | ||
<ModalPortal> | ||
<ModalLayout> | ||
<ToastModal message={children} /> | ||
</ModalLayout> | ||
</ModalPortal> | ||
); | ||
} |
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.
childern을 prop으로 받아주는건가?
export const St = { | ||
centerFlex, | ||
centerFlexColumn, | ||
Input, | ||
Button, | ||
InputFlagWrapper, | ||
}; |
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.
오옹.. 신기하다 St 네이밍을 하면서 파일을 분리시켜줬네!
const InputFlagWrapperSignup = styled(St.InputFlagWrapper)` | ||
width: 40rem; | ||
`; | ||
|
||
const InputInSignup = styled(St.Input)` | ||
width: 25rem; | ||
`; | ||
|
||
const DoubleInputWrapper = styled.div` | ||
${St.centerFlex}; | ||
gap: 1rem; | ||
`; |
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.
혹시 잘 몰라서 St.InputFlagWrapperSingup과 DoubleInputWrapper의 차이를 물어봐도 될까?
✨ 구현 기능 명세
🧩 기본 과제
[ 로그인 페이지 ]
로그인
/mypage/:userId
로 넘어갑니다.userId
는 로그인 성공시 반환 받은 사용자의 id 입니다.회원가입 이동
/signup
으로 이동합니다.[ 회원가입 페이지 ]
중복체크 버튼
isExist : true
isExist : false
회원가입 버튼
/login
으로 이동합니다.[ 마이 페이지 ]
/mypage/:userId
의userId
를 이용해 회원 정보를 조회합니다./login
으로 이동합니다.🌠 심화 과제
[ 로그인 페이지 ]
createPortal
을 이용합니다.로그인 실패시 response의 message를 동적으로 받아 토스트를 띄웁니다.
[ 회원가입 페이지 ]
비밀번호 확인
중복체크
생각 과제
🖤 API 통신에 대하여
로딩 / 에러 처리를 하는 방법에는 어떤 것들이 있을까?
패칭 라이브러리란 무엇이고 어떤 것들이 있을까?
패칭 라이브러리를 쓰는 이유는 무엇일까?
💎 PR Point
1️⃣
router
설정2️⃣ 로그인 구현 + toastModal
-> 로그인 post 구현입니다!
-> 모달은 400에러가 사용자가 없을 때더라구요! 그때 message를 받아와서, Modal의
children
안에 넣어두었습니다.토스트 모달이기에, 3초정도 지속하고 사라지도록
useEffect
로 구현하였습니다.3️⃣ 회원가입
❤️ 로그인에 비해 state 수가 워낙 많아서 useReducer를 사용해 주었어요!
⭐ 각각의 친구들(?)을 제어하는 함수를 만들었습니다! ⭐
🧡 회원가입 post
💛 비밀번호 확인
💙 중복버튼 체크 api 통신
💜 중복 버튼 체크 스타일 변화
=> 회원가입 비활성화도 비슷하게 구현되었습니다!
4️⃣ 마이페이지
❤️ 마이페이지 api 통신
🧡 로그아웃 버튼 클릭시 로그인으로 이동 ( 로그인에서 회원가입 이동도 같은 맥락으로 구현)
5️⃣ 폴더 구조 및 설계
🥺 소요 시간, 어려웠던 점
7h-8h
🌈 구현 결과물
1️⃣ 로그인하러가기 + 회원가입으로 이동
https://github.com/DO-SOPT-WEB/HyeinKwon/assets/100409061/1bd29b85-2a87-4a88-9949-eb84a69ba8a3
2️⃣ 로그인 성공시 마이페이지로 이동 + 마이페이지 회원정보 조회
_2023_11_17_10_04_59_316.mp4
3️⃣ 로그아웃 버튼 누르면 로그인으로 이동 + 로그인 실패하면 toast모달 띄우기(3초뒤 사라짐)
_2023_11_17_10_06_43_4.mp4
4️⃣ 로그인 화면에서 회원가입으로 이동 + 아이디 중복 확인(체크하지 않은 경우 검정, 중복인 경우 빨강, 중복 아닌 경우 초록, 중복체크 후 id값 변경하면 다시 색 돌아가기)
https://github.com/DO-SOPT-WEB/HyeinKwon/assets/100409061/8a4d3e11-1c42-49b7-aaf9-39ae93f47682
5️⃣ 중복체크시 중복 체크 일 때 회원가입 버튼 비활성화
https://github.com/DO-SOPT-WEB/HyeinKwon/assets/100409061/833c0d34-fa35-4706-9ca9-b7ea98f61d0a
6️⃣ 중복체크 풀고 모두 다 입력완료 시 회원가입 버튼 활성화 + 회원가입 되면 로그인 페이지로 이동
https://github.com/DO-SOPT-WEB/HyeinKwon/assets/100409061/b9543217-00b2-4f11-a377-272a07685e3c
7️⃣ 회원가입 실시한 아이디 + 비밀번호로 로그인 성공, 성공 후 마이페이지 이동 => 회원가입 성공
_2023_11_17_10_10_59_580.mp4
8️⃣ 회원가입 버튼 비활성/활성화 조건 모두 구현
_2023_11_17_10_11_58_955.mp4