-
Notifications
You must be signed in to change notification settings - Fork 1
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주차 기본/공유 과제] 🔗 로그인, 회원가입 구현해보기 #6
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.
이렇게 상수 데이터를 따로 모아두셨군요! 덕분에 각 컴포넌트에서 기능적으로 꼭 필요한 코드들만 작성되어 있어 훨씬 간결해진 것 같네요! 저도 다음부터는 상수데이터를 분리해 봐야겠어요!
const Login = () => { | ||
const navigate = useNavigate(); | ||
const [inputVal, dispatch] = useReducer(reducerFn, initialLoginState); | ||
|
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로 ID와 password의 상태를 관리하신 부분이 정말 인상적입니다! +0+
저번 과제 이후 useReducer과 useState를 언제 어떻게 선택해야 할지에 대한 고민이 있던 찰나였습니다...
제가 이전에 찾아보았을 때는 배열, 객체와 같이 보다 복잡한 상태의 값을 관리할 경우 useReducer을 사용하는 게 좋고, 그렇지 않을 경우 코드 크기나 가독성을 고려해 useState를 사용하는 게 좋다고 결론을 내렸었는데,
useState와 useReducer 사용에 서진님의 기준이 있으신지도 여쭙고 싶습니다!
}; | ||
case 'inputVoidError': | ||
return { ...state, inputVoidErrorMessage: action.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.
에러 처리까지 useReducer로 관리하니 로직이 정말 깔끔하고 간결해 보이네요!!
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.
p5) 저도 reducer 쓸 생각은 안했는데 state가 많으니까 reducer를 사용하는게 코드가 엄청 깔끔해지네요!
const Button = (props) => { | ||
const { content, onClick } = props; | ||
return ( | ||
<ButtonWrapper {...props} onClick={onClick}> |
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.
스프레드 연산자로 prop의 모든 값을 한번에 넘겨줄 수도 있군요! 서진님 덕분에 새롭게 배워가요!!!
이렇게 {...props}를 작성할 경우 {...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.
Button.jsx에서의 ButtonWrapper과 컴포넌트명이 중복되는 것 같아욧!! 혼선을 방지하기 위해 ButtonWrapper.jsx의 ButtonWrapper과 Button.jsx의 ButtonWrapper의 컴포넌트명을 다르게 수정하면 좋을 것 같습니다!
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.
깔끔한 코드 잘 보고갑니다! 파일 분리, 상수 데이터등 분리를 많이 하셔서 코드를 짜니까 확실히 코드들이 간결하고 가독성도 좋네요!! 특히 reducer를 활용해서 여러 input state들을 관리하니 코드의 구조가 비슷해서 이해하기 훨씬 편했습니다~~~ 좋은 코드 잘 보고가고 이번 합세때도 좋은 코드 많이 알려주고 보여주시길 바랍니다ㅎ
export const client = axios.create({ | ||
baseURL: import.meta.env.VITE_APP_BASE_URL, | ||
headers: { 'Content-Type': 'application/json' }, | ||
}); |
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.
p5) axios.create로 axios 인스턴스를 만들고 불러와서 사용할수 있네요!! 배워갑니다..
$hoverFontColor = 'white', | ||
$hoverColor = 'blue', | ||
}) => css` | ||
margin-top: ${$marginTop}; |
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.
p5) 혹시 여기서만 css 로 css 설정을 해주신 이유가 있을까요??
const { inputVoidErrorMessage, ...requestBody } = inputVal; | ||
try { | ||
const response = await patchChangePw(requestBody, userId); | ||
alert(`✨ ${response.data.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.
p5) 휘황찬란한 텍스트 좋아요
} catch (error) { | ||
if (error.response) { | ||
const status = error.response.status; | ||
if (status === 400 || status === 403) { |
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.
p5) 500 에러는 제외하셨는데 혹시 이유를 알 수 있을까요??
<GlobalStyle /> | ||
<App /> | ||
</ThemeProvider> | ||
</> |
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.
p5) themeProvider로 한번 감싸줫는데 혹시 Fragment로 한번 더 감싼 이유가 있을까요??
return ( | ||
<LoginSignupWrapper title="LOGIN"> | ||
<LoginImg src="./src/assets/img/loginImg.jpeg" alt="로그인 이미지" /> | ||
{LOGIN_LABEL.map((label, idx) => ( |
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.
p5) 확실히 값들을 상수로 저장해서 map 메서드를 사용해서 요소들을 생성하는게 데이터 만들기는 귀찮아도 코드는 깔끔해지는것 같네요!
<MainWrapper> | ||
<MainImg src="/src/assets/gifs/modalCongrats.gif" loop="infinite" /> | ||
<ButtonWrapper> | ||
<Button content="MY PAGE" onClick={onClickMypage} /> |
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.
p5) 제가 생각했을땐 MY PAGE 같은 text정도는 prop으로 안사용하고 MY PAGE 으로 적어도 괜찮지 않나? 라고 생각했었는데 이렇게 text값들도 prop으로 넘겨서 사용할때의 장점이 있을까요??
}; | ||
case 'inputVoidError': | ||
return { ...state, inputVoidErrorMessage: action.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.
p5) 저도 reducer 쓸 생각은 안했는데 state가 많으니까 reducer를 사용하는게 코드가 엄청 깔끔해지네요!
✨ 구현 기능 명세
🧩 기본 과제
로그인 페이지
회원가입 페이지
마이페이지
🔥 심화 과제
메인페이지
로그인 페이지
회원가입 페이지
input이 비어있는 상태로 api연결 시도했을시
해당 input 테두리 색상 변경
input에 focus 맞추기
api요청 금지
전화번호 양식 정규표현식으로 자동입력되도록 설정 (숫자만 입력해도 "-"가 붙도록)
비밀번호 검증 유틸 함수 구현 (검증 통과되지 않을시 api요청 금지)
공유과제
링크 첨부(팀 블로그 링크) :https://forweber.palms.blog/lighthouse
📌 내가 새로 알게 된 부분
상수데이터
각 페이지의 input 컴포넌트에서 필요한 값들을 미리 정의해 둔 후, map 을 사용하여 렌더링 하였습니다.
공통 컴포넌트
1. 버튼
1️⃣ 버튼을 감싸는 wrapper 컴포넌트에 children을 Prop으로 받아서 재사용
2️⃣ 버튼의 content와 style관련 코드를 prop으로 받아서 재사용
3️⃣ 기본 스타일을 미리 정의해둔 후, prop으로 받아온 값에 따라 버튼 스타일 변경
api 관련 함수 커스텀 훅으로 분리
컴포넌트 내부에 사이드이펙트를 담당하는 api 호출 함수를 포함하는 것은 좋지 못하다고 생각해서 로직 관련 함수는 따로 분리하여 사용하였습니다.
1️⃣ axios 객체 생성
2️⃣ api 호출 함수 작성
3️⃣ api 함수를 컴포넌트에서 사용하는 로직에 추가하여 연결한 후 커스텀훅으로 정의
4️⃣ 필요한 컴포넌트에서 호출하여 사용
로그인/회원가입/비밀번호 변경 input에 입력받은 값 useReducer로 관리
1️⃣ useReducer에 전달할 초기 상태 정의
2️⃣ useReducer에 전달할 reducerFn 정의
3️⃣ useReducer 선언
4️⃣ input에 change 이벤트가 발생할 때마다 해당 input의 id 값에 따라 action.type을 정의하고, 입력된 value를 값으로 전달
5️⃣ 업데이트 된 reducer의 현재 상태값인 inputVal을 api의 인자로 전달
-> api의 인자로 바로 사용하기 위해서, api 명세서에 나와있는 필드명을 이용하여 reducer 상태객체의 key값을 정의해두었습니다.
💎 구현과정에서의 고민과정(어려웠던 부분) 공유!
딱히 없숨다!
🥺 소요 시간
8h
🌈 구현 결과물
노션 링크 첨부합니다