-
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
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.
디자인이 너무나도 깔쌈하고.. 심화과제까지 완벽하게 해낸 우리 갓기 칭찬해~ 이모티콘 하나씩 넣었다고 훨씬 더 보기 좋은거 있지?! 그리고 상수화 시킨거 너무 인상적이였어.. 고생해따!!!!!
@@ -0,0 +1,16 @@ | |||
<!doctype html> | |||
<html lang="ko"> |
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 Input = ({ | ||
pageType, | ||
inputType, | ||
onInputChange, | ||
isAvailable, | ||
setIsAvailable, | ||
}) => { |
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.
사실 나도 이렇게 했는데 .. props로 받아와서 구조분해할당으로 주는게 조금 더 깔끔한거 같기도 해... 내 개인적인 생각이야..!
const Input = ({ | |
pageType, | |
inputType, | |
onInputChange, | |
isAvailable, | |
setIsAvailable, | |
}) => { | |
const Input = (props) => { | |
const { pageType, inputType, onInputChange, isAvailable, setIsAvailable } = props; |
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 const CHECK = { | ||
NOT_CHECKED: 0, | ||
EXIST: 1, | ||
NOT_EXIST: 2, | ||
}; |
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 [inputValue, setInputValue] = useState(""); | ||
|
||
const handleChange = (e) => { | ||
setIsAvailable && setIsAvailable(CHECK.NOT_CHECKED); |
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에 쓰여진 값이 바뀔 때마다 setIsAvailable (중복체크 관련 state)를 NOT_CHECKED(중복체크 버튼 검정색)로 바꿔주는 그런 ... 조건인가?!
|
||
return ( | ||
<Sign.InputWrapper> | ||
<img src={iconSrc} /> |
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.
img 태그에 alt 추가해주기!
useEffect(() => { | ||
const validateInputs = () => { | ||
const requiredInputs = [INPUT.ID, INPUT.PW, INPUT.PWCHECK, INPUT.NAME]; | ||
const areInputsFilled = requiredInputs.every( |
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.
오...! .every
처음봤어.. forEach
랑 뭐가 다른걸까 싶어서 찾아봤는데 every 다음에 오는 함수가 모두 통과하는지 검사하고 boolean값을 반환한다는 점이 다른거 같긴 하다! 하나 새로 알아가!
const Title = ({ page }) => { | ||
switch (page) { | ||
case PAGE.LOGIN: | ||
return <TitleText>로그인</TitleText>; | ||
case PAGE.SIGNUP: | ||
return <TitleText>회원가입</TitleText>; | ||
case PAGE.MYPAGE: | ||
return <TitleText>마이페이지</TitleText>; | ||
} | ||
}; |
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.
우왕 난 그냥 페이지마다 박아줬는데 이렇게 하면 페이지들 더 추가했을 때 유지보수하기 좋을거 같다!!
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.
이거 너무 아이디어 좋은데용? 리팩할 때 써먹ㅇㅓ야지~
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 RequestLogin = async () => { | ||
await axios | ||
.post( | ||
import.meta.env.VITE_BASE_URL + "/api/v1/members/sign-in", |
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.
헉 요렇게 +로 이어주는거 처음봤다..! 이렇게도 가능하구나..?
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.
혹시 ${}
이거 안 쓴 이유가 있을까아?
useEffect(() => { | ||
const fetchData = async () => { | ||
const path = location.pathname; | ||
const idFromURL = path.substring(path.lastIndexOf("/") + 1); | ||
try { | ||
const data = await axios.get( | ||
import.meta.env.VITE_BASE_URL + `/api/v1/members/${idFromURL}` | ||
); | ||
setID(data.data.username); | ||
setName(data.data.nickname); | ||
} catch (error) { | ||
console.error(error); | ||
} | ||
}; | ||
fetchData(); | ||
}, [location]); |
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.
혹시 여기서 26번째 줄에 fetchData()
는 왜 넣어줬는지..? 무슨 역할을 하는지 알려줄 수 있을까?! 딱 저부분만 이해를 못했어..
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.
갓기야 구경왔다가 디자인에 화들짝 놀라구 간다 ........ 갓기 폼미 ..💗💗
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.
굿굿! 일단 수비니는 상수화에 진짜 능한 거 같아! 나는 그냥 아무 생각없는 것도 뚝딱 상수화하니까 되게 가독성이 좋아지는 것 같아요!! 그리고 commonStyle 따로 빼준 거 너무너무 칭찬해!! 너무 잘 한 거 같아요
로직같은 거는 딱히 내 눈엔 손 댈게 없는 것 같고,, 나중에 fetch 함수들을 utils로 빼서 활용하는 방식으로 리팩토링 해줘도 많이 좋을 것 같다는 생각이 드네요!
진짜 늘 느끼지만 하나하나 정성스럽게 코드 짜주는 것 같아서 내가 다 고마워!
const Input = ({ | ||
pageType, | ||
inputType, | ||
onInputChange, | ||
isAvailable, | ||
setIsAvailable, | ||
}) => { |
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 [inputValue, setInputValue] = useState(""); | ||
|
||
const handleChange = (e) => { |
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.
아예 hanldeChange함수를 빼버렸구나!!?
onInputChange(inputType, e.target.value); | ||
}; | ||
|
||
useEffect(() => { |
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.
너무 깔끔해!! 좋아요좋아요!
|
||
return ( | ||
<Sign.InputWrapper> | ||
<img src={iconSrc} /> |
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.
img 태그에 alt 추가해주기!
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.
귀여워,,,,,,,,,,,,,,,,,,,,,,
<ToastWrapper> | ||
<ToastMessage>{message}</ToastMessage> | ||
</ToastWrapper>, | ||
document.body |
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 RequestLogin = async () => { | ||
await axios | ||
.post( | ||
import.meta.env.VITE_BASE_URL + "/api/v1/members/sign-in", |
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 [name, setName] = useState(""); | ||
|
||
useEffect(() => { | ||
const fetchData = async () => { |
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.
함수 분리시켜주는게 더 가독성 있을 것 같아요!
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.
useEffect 밖으로 뺄 수 있을거야!
const data = await axios.get( | ||
import.meta.env.VITE_BASE_URL + `/api/v1/members/${idFromURL}` | ||
); | ||
setID(data.data.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.
요런거 나중에 점점 많아지면 구조분해할당으로 바꿔줘도 좋습니다!
import.meta.env.VITE_BASE_URL + `/api/v1/members/check?username=${id}` | ||
); | ||
data.data.isExist | ||
? setIsAvailable(CHECK.EXIST) |
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.
굿굿 너무 깔끔하다!
case INPUT.ID: | ||
setIconSrc(loginIcon); | ||
setPlaceholderText("아이디"); | ||
break; | ||
case INPUT.PW: | ||
setIconSrc(passwordIcon); | ||
setPlaceholderText("비밀번호"); | ||
break; | ||
case INPUT.PWCHECK: |
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을 상수화 시켜준 이유가 나오는구나!
const logout = () => { | ||
navigate("/login"); | ||
}; |
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.
다른 상수로 해서 onClick에 넣어주는거 너무 좋다
✨ 구현 기능 명세
🌱 기본 조건
.env
파일 사용하기🧩 기본 과제
[ 로그인 페이지 ]
/mypage/:userId
로 넘어갑니다. (여기서userId
는 로그인 성공시 반환 받은 사용자의 id)/signup
으로 이동합니다.[ 회원가입 페이지 ]
중복체크 버튼
회원가입 버튼
/login
으로 이동합니다.[ 마이 페이지 ]
/mypage/:userId
의 userId를 이용해 회원 정보를 조회합니다.🌠 심화 과제
[ 로그인 페이지 ]
createPortal
을 이용합니다.[ 회원가입 페이지 ]
비밀번호 확인
중복체크
생각과제
💎 PR Point
week3 의 커밋 내역들이 딸려와서 그거 삭제하고 삽질하고 하다가 커밋이 저렇게 하루로 묶여버림 이슈 하.. 😩
저는 이번 과제에서
컴포넌트 재사용성
,관심사에 따른 코드 분리
,컴포넌트의 단일 책임
에 신경을 써봤어요♻️ 로그인 & 회원가입 컴포넌트 재사용
로그인과 회원가입 화면이 유사한 구조를 갖고 있어서 SignForm 컴포넌트로 정의한 후 조건부 렌더링을 통해 구현했어요
♻️ Input 컴포넌트 재사용
Input 도 4번 반복 되기 때문에 따로 빼주어서 props를 이용해 구현했습니다
🥢 분리할 수 있는 로직은 분리
서버 통신이 필요한
Login
,SignUp
,DoubleCheck
로 따로 분리했어요!로직을 분리했기 때문에 수정 시에도 찾기 쉬웠답니당
📋 배열 순환에 every() 사용
array.every()
는 배열을 순환하면서 모든 요소가 조건에 부합하면 true, 아니면 false를 반환합니다이 메소드를 통해 조건에 부합하는 지 쉽게 확인 할 수 있었어요
🧮 대괄호 표기법 (Computed Property Name) 사용
객체의 속성 이름을 동적으로 결정하여 inputValue 업데이트를 간편하게 구현하였어요
🥺 소요 시간, 어려웠던 점
11h
저번 과제를 하면서 리액트와 styled-component에 익숙해져서 구현은 그렇게 오래걸리지 않았지만
컴포넌트 설계를 고민하는데에 많은 시간을 썼어요
🌈 구현 결과물
회원가입
signup.mov
회원가입 버튼 활성화
check.mov
로그인 성공
&로그아웃
login.mov
로그인 실패
login_failed.mov