-
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주차 기본/심화/공유 과제] 회원가입 & 로그인 #5
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.
희선님 4주차 과제도 고생많으셨어요😄
오랜만에 보는 테일윈드여서 반가웠네요! 전체적으로 구조도 너무 잘짰고, 스타일링은 말할것도 없네요. api 로직 분리해서 사용한 부분도 많이 배울 수 있었습니다. 합세 기간 동안도 잘부탁드립니다.
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.
p1: 현재 .env
파일이 그대로 노출되어 있습니다. .gitignore
에 .env
를 추가해주어서 git
에 올라가지 않도록 하는 것이 좋을 것 같습니다. 아마 깜빡하고 놓친 부분이겠죠?
|
||
return ( | ||
<div> | ||
<Header /> |
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.
p3: 현재 mypage와 hobby 컴포넌트에서 모두 공통적으로 Header
컴포넌트를 불러와서 사용하고 있는데 Layout으로 설정해서 공통으로 불러와서 사용할 수도 있게 할 수 있을거 같아요
path: 'mypage', | ||
element: <MyPage />, | ||
}, | ||
{ | ||
path: 'hobby', | ||
element: <Hobby />, |
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: 저는 조건부 렌더링 방식으로 버튼 클릭시 mypage와 hobby 컴포넌트를 렌더링 해주는 방식으로 구현 했는데, 각각 페이지로 만드는건 생각못했네요!!
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.
p2: 각 단계에서 렌더링되는 입력 필드를 컴포넌트로 분리하면 가독성과 관심사 분리 차원에서 더 좋을 것 같아요!
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: 별도의 HTTP 요청 함수를 정의해 두니 재사용성도 증가하고, 훨씬 효육적인거 같네요. 배워갑니다!
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: 저는 급하게하느라 api로직을 분리하지 못했는데, 반성하게 되네요.
const [errors, setErrors] = useState({ | ||
username: false, | ||
password: false, | ||
confirmPassword: false, | ||
hobby: 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.
p2: 현재 유효성 검사 상태를 관리하는 errors를 사용하고 있지만, 개별적으로 업데이트하고 있네요. 유효성 검사를 단계별로 관리할 수 있게 해주어서 가독성을 높일 수 있을 것 같아요!
</div> | ||
{errors.password && ( | ||
<p className='text-red-600 mt-4 text-sm'> | ||
비밀번호를 8자 이하로 입력해주세요 |
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.
p3: 다음과 같은 유효성 검사 메시지는 별도의 상수 객체로 분리해서 사용하면 관리하기 더 좋을거 같아요!
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.
tailwind 도 theme 이 있군요.. 🤔
styled-component 랑 두개를 섞어서 쓴 건가요??!
설정하는 것에서 쉽지 않았을 것 같아요,,
코드를 전체적으로 밖으로 빼는 방식으로 구현하셔서 보기에 너무 깔끔했습니다!
4주차 너무 고생하셨습니다 !!!! :)
} from '../../utils/cardUtil'; | ||
|
||
const GameBoard = ({ gameLevel, startGame, stopGame, setTimer }) => { | ||
const { firstSet, secondSet } = LEVELS[gameLevel]; |
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: 이렇게 Levels 로 빼서 작성하는 방법 좋은 것 같습니다 !!🥺
const Modal = ({ isOpen, onClose, message }) => { | ||
if (!isOpen) return null; | ||
console.log(message); | ||
|
||
return ReactDOM.createPortal( | ||
<Overlay> | ||
<ModalContainer> | ||
<p>✨ 1 to 50 ✨</p> | ||
<Message>{message}</Message> | ||
<Button onClick={onClose}>확인</Button> | ||
</ModalContainer> | ||
</Overlay>, | ||
document.getElementById('modal-root') // `index.html`에 모달을 렌더링할 DOM 요소 추가 필요 |
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: 저는 모달을 빼야지 빼야지 했다가 시간 없어서 뒀었는데, 빼셨네요.. 리스펙...........✨
export const LEVELS = { | ||
level1: { firstSet: 9, secondSet: 18 }, // 첫 번째 세트: 1~9, 두 번째 세트: 10~18 | ||
level2: { firstSet: 16, secondSet: 32 }, // 첫 번째 세트: 1~16, 두 번째 세트: 17~32 | ||
level3: { firstSet: 25, secondSet: 50 }, // 첫 번째 세트: 1~25, 두 번째 세트: 26~50 | ||
}; |
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: 너무 깔끔하고 좋습니다....🥺
useEffect(() => { | ||
const interval = setInterval(() => { | ||
if (isTimerStarted) { | ||
setTimer((prev) => prev + 0.01); | ||
} | ||
}, 10); | ||
return () => clearInterval(interval); | ||
}, [isTimerStarted]); | ||
|
||
useEffect(() => { | ||
initializeGame(); | ||
}, [gameLevel]); |
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.
p3: react 공식문서에 의하면
When you’re not sure whether some code should be in an Effect or in an event handler, ask yourself why this code needs to run. Use Effects only for code that should run because the component was displayed to the user.
-> 사용자에게 해당 컴포넌트가 보여졌다는 이유만으로도 호출되어야 하는 코드는 useEffect를 사용하고, 사용자와 인터랙션이 있을 때는 useEffect를 사용하지 않는 편이 좋다.
라고 합니다!
저도 useEffect 를 자주종종 쓰긴 하지만 참고용으로 언급 드려요!
}, []); | ||
|
||
const handleGetUserHobby = async (e: React.FormEvent) => { | ||
e.preventDefault(); |
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.
p4: 이 e.preventDefault();
해당 코드가 여기서 쓰이는 이유가 궁금합니다,,!
if ('result' in response) { | ||
localStorage.setItem('accessToken', response.result.token); | ||
console.log('로그인 요청결과:', response); // 요청 결과 콘솔로 출력 |
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.
p3: 전체적으로 데이터를 확인하기 위한 console 을 제거하는 게 좋을 것 같아요!
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.
안녕하세요 희선님!! 전반적으로 폴더구조를 잘 쪼개주셔서 동작에 따라 어떤 코드를 참고하면 되는지 바로 찾을 수 있어서 좋았던 것 같습니다. 다만 (물론 저도.. 콘솔지우기 습관이 덜들었지만요) 콘솔이 이곳 저곳 남아있는 곳이 있는 것 같아서, 테스트해보고 필요없어진 콘솔로그는 지우는 게 좋을 것 같아요!!
코드 보면서 많이 배워갑니다. 짱!!!
✨ 구현 기능 명세
💡 기본 과제
취미
,내 정보
메뉴 탭로그아웃
버튼취미
,내 정보
취미 페이지, 내 정보 페이지 출력 (1개의 페이지로 구현해도 되고, url 달라도 됨)🔥 심화 과제
공유과제
제목:
링크 첨부 :
❗️ 내가 새로 알게 된 점
커밋이 좀 꼬여서 , 11월 12일 커밋부터 봐주시면 됩니다 ㅠㅠ
원래
tailwind CSS
가 익숙해서 이번 과제는 tailwind로 구현했습니다!! (괜찮겠죠?? ㅎㅎ..). 사실 이전에는 tailwindCSS를 사용할때 globalstyle, themeProvider를 설정하지 않아서 몰랐는데 styled-component와 함께 사용할 수 있다는 걸 알게 되었습니다. (당연한 것 같기도) 그래서theme.ts
와tailwind.config.ts
에서 사용하는 색상을 같게 하기 위해서 styles폴더에 colors.ts를 추가해 같은 색상명을 공유하도록 설정했습니다!이전 Typescipt+react 프로젝트를 진행해서 서버와 통신할때는 보통 Swagger 문서를 프로젝트에 바로 연동하는 편이여서 성공시 response, 실패시 response, 요청 request를 딱히 크게 고려하지 않고 바로바로 불러와서 사용하는 편이었는데, 이번에는 types에 서버 명세서를 보고 입력해보았습니다. 직접 작성하다 보니 필요한 값이 뭔지, 더 잘 이해하면서 작업할 수 있었던 것 같습니다 !!!
Token을 헤더에 함께 보낼때,
Bearer ${token}
인지.. 그냥 token인지 많이 헷갈렸었습니다 ㅠㅠ 참고 문서를 봐도 다 다르게 나와서.. 세미나 시간에 사용해보았던 Thunder Client로 직접 보내보고 그에 맞게 작성하다보니 해결되었습니다. 역시 직접해보는 것이 제일 중요한 것 같습니다!❓ 구현 과정에서의 어려웠던/고민했던 부분
1. 회원가입 시 단계별로 다른 컴포넌트를 보여주기
const [step, setStep] = useState(1);
1단계로 설정2. 회원가입 시 입력 필드에 대한 유효성 검사
-api.ts에는 get, post, put의 HTTP 요청을 처리하는 함수들을 정의해두었습니다. 여기서 정의해두었던 axiosInstance를 사용했어요
-authApi에는 유저와 관련된 api, hobbyApi에는 취미 관련 api를 작성했습니다. 미리작성해두니 페이지 안에서 함수 response를 받는 부분이
const response = await getMyHobby();
처럼 간단해졌습니다.유저 정보를 변경하는 request에는 취미, 비밀번호, 헤더를 모두 포함해서 보내놓게 작성해두고 axiosInstance에 이미 토큰이 포함되어있으니까 updataData에는 취미랑 비밀번호만 작성해야겠다. 하고 작성했더니 타입 불일치가 계속 떠서, 전 토큰 문제인지 axiosInstace를 잘못 작성한건지 updateUser 함수를 잘못 작성한건지 한참 헤멨는데, 그냥 PutUserRequest 자체에 헤더가 포함이 되지 않아도 자동으로 붙여지는 것이기 때문에 PutUserRequest에서 headers를 지웠더니.. 아주 말끔하게 해결되었습니다! 역시... 인과관계를 잘 살펴봐야하는 것 같습니다 ㅠㅠ
🥲 소요 시간
12h
🖼️ 구현 결과물
default.mp4
8.mp4
default.mp4
default.mp4
default.mp4