-
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주차도 너무 고생 많으셨습니다 :) 👍🏻👏🏻👏🏻
try { | ||
const response = await axios.post( | ||
`${import.meta.env.VITE_BASE_URL}/login`, | ||
{ | ||
username, | ||
password, | ||
} | ||
); |
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: axios 환경 세팅으로 BASE_URL 을 지정할 수 있어요!
사용하는 배포된 api url 가 2개 이상이라면 이렇게 지정하면 안되겠지만,
지금처럼 한개의 api만 사용한다면 이렇게 지정해두는 방법도 있습니다!
/login 등 api 경로를 다른 파일로 나눠둔 후 axios.get(PATH_API.MY_HOBBY)
이런식으로 부르는 방법도 참고해주시면 좋을 것 같아요 !! 🍀
const api = axios.create({
baseURL: PATH_API.API_DOMAIN,
headers: {
'Content-Type': 'application/json',
},
// withCredentials:true, // 쿠키 cors 통신 설정
});
background: ${({ theme }) => theme.colors.gray2}; | ||
color: ${({ theme }) => theme.colors.white1}; | ||
border: none; | ||
border-radius: 5px; |
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: 보통 border-radius 는 px 로 처리하시는지 궁금합니다 !
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: 보통 border-radius 는 px 로 처리하시는지 궁금합니다 !
넵 저는 border 관련 스타일링은 px로 처리합니다! 해당 내용은 민정님 코리에 달았으니 참고 부탁드려요.
`${import.meta.env.VITE_BASE_URL}/user/my-hobby`, | ||
{ | ||
headers: { | ||
token: token, | ||
}, | ||
} | ||
); |
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: 헤더 세팅도 마찬가지로 axios 환경 세팅에서 가능합니다
매번 세팅하는 것보다 유지보수성 차원에서 좋을 것 같은데, 시간없어서 이렇게 하신 거라면 백번 이해합니다...........🥺🥺
api.interceptors.request.use(
(config) => {
// 요청 전 처리
const token = localStorage.getItem('accessToken');
if (token) {
config.headers.token = `${token}`;
}
return config;
},
(error) => Promise.reject(error),
);
{funnel.currentStep === "name" && ( | ||
<NameStep name={name} setName={setName} onNext={funnel.next} /> | ||
)} |
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: 오 funnel 은 처음 보는데, .next 하면 다음 스텝으로 넘어가는 시스템인가보네요!
저도 step 부분에서 코드가 더러워질 것 같아서 고민을 좀 했었는데,
이런 방식으로 짜면 좀 더 깔끔해질 것 같네요 !! 배워갑니다..👏🏻
function useFunnel<T>(steps: T[]): UseFunnelReturnType<T> { | ||
const [currentIndex, setCurrentIndex] = useState(0); | ||
|
||
const next = () => { | ||
setCurrentIndex((prevIndex) => | ||
prevIndex < steps.length - 1 ? prevIndex + 1 : prevIndex | ||
); | ||
}; | ||
|
||
const prev = () => { | ||
setCurrentIndex((prevIndex) => (prevIndex > 0 ? prevIndex - 1 : prevIndex)); | ||
}; | ||
|
||
const reset = () => { | ||
setCurrentIndex(0); | ||
}; |
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: 코드 엄청 깔끔하고 좋네요.. 👍🏻
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: PR에 남겨주신 퍼널이군요!! 많이 배워갑니다 ㅎㅎ
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.
역시 리드다운 코드군요 .. 👍 딱히 집히는 부분 없이 술술.. 술술 읽혔습니다 ...
사실 스타일링 하다보면 컴포넌트 이름을 대충 짓게 될 때도 있는데 네이밍이나 funnel, 또 pr에 남겨주신 dispatch 부분들도 코드를 보면서 이런식으로 사용하는 구나 - 하고 많이 배워가는 것 같아요. 민정님 의견처럼 api 관련 부분만 리팩토링하면 더 좋을 것 같습니다! 사실 웹 1팀 중에 마지막으로 코드 리뷰를 진행했는데 다른 분들 코드에 남겨주신 코멘트랑, 건휘님 코드 보고 합세 코드 빨리 고쳐야겠다고 생각중입니다.. 하하 ㅎㅎㅎ 4주차 과제 너무 고생많으셨습니다!!
<NavItem | ||
active={activeTab === "hobby"} | ||
onClick={() => setActiveTab("hobby")} | ||
> | ||
취미 | ||
</NavItem> | ||
<NavItem | ||
active={activeTab === "info"} | ||
onClick={() => setActiveTab("info")} | ||
> | ||
내 정보 | ||
</NavItem> |
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: 저는 취미랑 정보페이지를 따로 만들어서 이동하게 했는데, 이렇게도 구현할 수 있었네요. 배워갑니다!
const NavItem = styled.span<{ active: boolean }>` | ||
font-size: 1.2rem; | ||
cursor: pointer; | ||
color: ${({ active }) => (active ? "white" : "#ddd")}; |
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: 저는 active 상태에 따라 다른 색을 보여주고 싶을때, inactive, active로 이름을 붙여서 사용하는 편인데 참고해주셔도 좋을것 같아요! 여기 하나는 #ddd로 색상이 정의되어있어서 제안드립니다 ㅎㅎ
function useFunnel<T>(steps: T[]): UseFunnelReturnType<T> { | ||
const [currentIndex, setCurrentIndex] = useState(0); | ||
|
||
const next = () => { | ||
setCurrentIndex((prevIndex) => | ||
prevIndex < steps.length - 1 ? prevIndex + 1 : prevIndex | ||
); | ||
}; | ||
|
||
const prev = () => { | ||
setCurrentIndex((prevIndex) => (prevIndex > 0 ? prevIndex - 1 : prevIndex)); | ||
}; | ||
|
||
const reset = () => { | ||
setCurrentIndex(0); | ||
}; |
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: PR에 남겨주신 퍼널이군요!! 많이 배워갑니다 ㅎㅎ
type="text" | ||
placeholder="아이디" | ||
value={username} | ||
onChange={(e) => setUsername(e.target.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:코리 달다보니까 여기에 'e'가 'any' 타입이라고 하는데요! 사실 제가 해결방법을 몰라서... 찾아보니 들어오는 값에 따라서 e:string 하면 해결될 것 같다는 생각이 드네요!!
const handleInputChange = (event: React.ChangeEvent<HTMLInputElement>) => { | ||
const value = event.target.value; | ||
setName(value); | ||
|
||
if (value.length > 8) { | ||
setNameError("이름은 8글자 이하로 입력해주세요"); | ||
} else { | ||
setNameError(""); | ||
} |
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: 제가 에러 구현을 못해내서(사실 컴포넌트 내에 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.
안녕하세요 건휘님!! 처음보는 퍼널 같은거 보면서 이런식으로도 구현가능하구나~ 깨닫는 코드 리뷰시간이었던 것 같습니다. 역시 리드... 합세 잘 부탁드려요!!!
✨ 구현 기능 명세
💡 기본 과제
취미
,내 정보
메뉴 탭로그아웃
버튼취미
,내 정보
취미 페이지, 내 정보 페이지 출력 (1개의 페이지로 구현해도 되고, url 달라도 됨)🔥 심화 과제
공유과제
제목: Typescript 왜 사용할까? 제대로 알고 사용하자
링크 첨부 : https://wave-web.tistory.com/121
❗️ 내가 새로 알게 된 점
React.Dispatch<React.SetStateAction>
상위 컴포넌트에서 useState 상태 변경 함수를 넘길 때 () => void 로 넘겼었는데 정의 할 수 있는 타입이 있었다.
Dispatch
와setStateAction
을 통해setState
함수의 타입을 정의해주면 상태 업데이트 필요 시 요구하는 인자와 반환 값을 정확하게 명시할 수 있다.setState
가 인자로 받고, 업데이트하게 될 값의 타입이string
임을 쉽게 파악할 수 있다. 상태를 문자열로 설정하거나, 이전 문자열을 기반으로 새로운 문자열을 설정할 수 있도록 한다.해당 프로퍼티의 의미를 알기 쉽게 함으로써 가독성을 좋게 하고, 추후 유지보수에도 용이하다.
boolean
인 경우에는React.Dispatch<React.SetStateAction<boolean>>
을 사용한다.❓ 구현 과정에서의 어려웠던/고민했던 부분
퍼널 로직으로 회원가입 페이지 관리하기
이번 과제 중에서 가장 많은 시간을 투자하고, 고민을 많이했던 부분입니다.
회원가입 페이지의 흐름이 이름 => 비밀번호 => 취미 순서로 입력되어야 하고, 한 페이지에서 관리하다보니 누가봐도 더러운 코드에 가독성도 많이 떨어지는 것이 느껴졌습니다.
https://www.youtube.com/watch?v=NwLWX2RNVcw
전에 우연히
퍼널 설계
관련한 영상을 본것이 기억이나, 해당 영상을 참고하여퍼널 설계
를 바탕으로 회원가입 페이지를 구현하였습니다.useFunnel.ts
이 useFunnel 훅은 여러 단계로 이루어진 UI 흐름(회원가입 단계를 순차적으로 진행하는 폼)을 관리할 수 있도록 돕는 커스텀 훅입니다. 현재 단계, 다음 단계로의 이동, 이전 단계로의 이동 등을 쉽게 처리할 수 있습니다.
step값에 따라 각 컴포넌트 UI를 조건부 렌더링 할 수 있습니다.
각 컴포넌트에서 다음 버튼을 누를 때 step 상태를 원하는 컴포넌트로 업데이트 된다.
이 방식을 통해 step이 추가되어도 유연하게 대응할 수 있고, 전역 상태를 사용하지 않아도 되어 어떤 상태가 어떤 UI에서 수집되는지도 한눈에 볼 수 있게 된다. => 확장 가능성, 가독성 up
🥲 소요 시간
12h
🖼️ 구현 결과물
회원가입
2024-11-12.3.51.46.mov
로그인, 취미 조회
2024-11-12.3.52.55.mov
마이페이지 - 내정보 수정
2024-11-12.3.55.03.mov