-
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주차 기본/심화/생각] 로그인/회원가입 #7
base: main
Are you sure you want to change the base?
Conversation
@@ -0,0 +1,13 @@ | |||
<!doctype html> | |||
<html lang="en"> |
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.
아 이거 언석이한테 리뷰 받았는데 우리 같이 ko로 바꾸는거 같이 습관들여보자 ㅋㅋㅋ 나도 내 습관 고쳐볼게
import { MainBox, Header } from "./style"; | ||
|
||
export default function MyPage() { | ||
let { userId } = useParams(); |
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 쓰면 안되는 이유가 있나?? 아니면 바뀌어야하는 값이니까 혹시몰라서 let 쓴거야??
const handleUsername = (e) => { | ||
setUsername(e.target.value); | ||
}; | ||
const handlePassword = (e) => { | ||
setPassword(e.target.value); | ||
}; | ||
const handlePasswordAgain = (e) => { | ||
setPasswordAgain(e.target.value); | ||
}; | ||
const handleNickname = (e) => { | ||
setNickname(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.
나 이 부분 내 pr에 고민이라고 남겼는데, 같이 확장성 있는 함수를 구현하는 방법 찾아보자 ㅎㅎ 아무래도 이런 input창이 백만개라면 하나하나 만들어 줄순 없을테니깐 !!
username: username, | ||
password: password, | ||
nickname: nickname, |
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.
나는 이거 계속 타이핑하기 귀찮아서 하나로 묶어서 따로 뺐는데, 한 번 고려해보면 좋을듯 !!
axios | ||
.get(import.meta.env.VITE_BASE_URL + "/api/v1/members/check", { | ||
params: { username: 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.
이 부분 우리가 아름이 코드 참고해서 axios 인스턴스 만들어주는(?) 방법으로 리팩토링해도 좋을듯해!!
useEffect(() => { | ||
if ( | ||
!isExist && | ||
password != "" && | ||
password === passwordAgain && | ||
nickname != "" | ||
) { | ||
setIsNotFull(false); | ||
} else { | ||
setIsNotFull(true); | ||
} | ||
}, [isExist, password, passwordAgain, nickname]); |
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.
나는 버튼 태그 자체에 disabled를 줘서 버튼 활성화 로직을 구현했는데, useEffect로 구현하는 방법도 있었네?? 두 방법이 어떤 장단점이 있는건지 함 찾아봐야겠다..
const fetchUserInfo = async () => { | ||
try { | ||
const response = await axios.get( | ||
import.meta.env.VITE_BASE_URL + `/api/v1/members/${userId}` |
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.
이번 과제도 너무너무 수고했어용 !
다만, 사용하지 않는 App.css, index.css 파일은 삭제해주고 theme, GlobalStyle과 같은 스타일 파일들을 만들어주는건 어떨까요 ?
<meta charset="UTF-8" /> | ||
<link rel="icon" type="image/svg+xml" href="/vite.svg" /> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
<title>Vite + React</title> |
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주차/login-signup/src/App.css
Outdated
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,19 @@ | |||
import { Route, BrowserRouter, Routes } from "react-router-dom"; | |||
import "./App.css"; |
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.
요거 안쓰는거 아닌가용?
<Link to="/signup"> | ||
<Button>회원가입</Button> | ||
</Link> | ||
{createPortal(toastElement, 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.
모달을 띄워주는 부분도 로그인과는 역할이 다른 부분이라 컴포넌트 분리를 해주는게 좋을 것 같아!
예를 들어 모달을 구현한 컴포넌트 이름을 Modal
이라고 가정한다면,
showModal && <Modal />
이런 식으로 보다 명확하고 직관적인 코드가 될 수 있겠지 ?!
<Section> | ||
<SectionTitle>ID</SectionTitle> | ||
<SectionInput | ||
value={username} | ||
onChange={handleUserName} | ||
placeholder="아이디를 입력해주세요" | ||
/> | ||
</Section> | ||
<Section> | ||
<SectionTitle>PASSWORD</SectionTitle> | ||
<SectionInput | ||
value={password} | ||
onChange={handlePassword} | ||
placeholder="비밀번호를 입력해주세요" | ||
/> | ||
</Section> |
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, password 같은 문자열 값을 넣어줬어.
얘네를 map으로 돌려서 각 index 별로 원하는 동작을 수행하게 해줬구 !
다양한 방법이 있겠지만 요런 방법도 있다는거 참고하면 좋을듯 합니당 ~
!isExist && | ||
password != "" && | ||
password === passwordAgain && | ||
nickname != "" |
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.
!isExist && | |
password != "" && | |
password === passwordAgain && | |
nickname != "" | |
!isExist && | |
password && | |
password === passwordAgain && | |
nickname |
요렇게도 구현해줄 수 있다 !
useEffect(() => { | ||
setButtonColor("black"); | ||
}, [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.
위에서 말한 것처럼 조건부 스타일링 적용하는 코드로 하면 요 useEffect도 없앨 수 있겠죵 ?!
onClick={() => { | ||
handleIdisExist(); | ||
}} | ||
style={{ backgroundColor: `${buttonColor} ` }} |
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.
인라인으로 스타일 지정해주는건 지양해주세용 !!
이유는 지난 pr들에 남겨놨으니 잘 알고 있겠죵 ?!
<Section> | ||
<SectionTitle>비밀번호</SectionTitle> | ||
<SectionInput | ||
type="text" | ||
value={password} | ||
onChange={handlePassword} | ||
placeholder="비밀번호를 입력해주세요" | ||
/> | ||
</Section> | ||
<Section> | ||
<SectionTitle>비밀번호 확인</SectionTitle> | ||
<SectionInput | ||
type="text" | ||
value={passwordAgain} | ||
onChange={handlePasswordAgain} | ||
placeholder="비밀번호를 다시 한 번 입력해주세요" | ||
/> | ||
</Section> | ||
<Section> | ||
<SectionTitle>NICKNAME</SectionTitle> | ||
<SectionInput | ||
type="text" | ||
value={nickname} | ||
onChange={handleNickname} | ||
placeholder="닉네임을 입력해주세요" | ||
/> | ||
</Section> |
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.
요기도 거의 동일한 구조의 코드가 반복되고 있으니까 요 부분 개선할 수 있는 방법을 생각해보고 리팩토링 때 꼭 ! 반영해주기 !!
border: 1px solid black; | ||
background-color: ${(props) => (props.disabled ? "#ccc" : "black")}; | ||
color: ${(props) => (props.disabled ? "#666" : "#fff")}; |
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.
이번 과제에서도 theme과 GlobalStyle을 따로 정의해주지는 않은 것 같은데 혹시 이유가 있을까용!?
지금은 프로젝트 규모가 작기 때문에 임의의 색을 쓰기도 하고 유지보수에도 큰 리소스가 들지 않아서 딱히 필요성을 못 느낄 수도 있어요.
그치만 앞으로의 협업 과정에서 프로젝트 규모가 커지고 디자인분들께서 전달해주신 색상만을 사용해야 하는데요,
매번 요런 형태로 색상코드를 입력해주는 것은 리소스도 많이 들고 숫자 하나라도 잘못 들어가면 아예 다른 색이 되기 때문에 스타일 파일을 만드는 것은 사실 불가피해요!
작은 프로젝트 + 혼자하는 프로젝트일수록 다양한 부분들을 연습할 수 있다고 생각하고 세미나에서 배운 내용들을 최대한 많이 적용해보는건 어떨까요 ~?
.post(import.meta.env.VITE_BASE_URL + "/api/v1/members/sign-in", { | ||
username: username, | ||
password: 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.
.post(import.meta.env.VITE_BASE_URL + "/api/v1/members/sign-in", { | |
username: username, | |
password: password, | |
}) | |
.post(`${import.meta.env.VITE_BASE_URL}/api/v1/members/sign-in`, { | |
username, | |
password, | |
}) |
템플릿 리터럴과 단축 프로퍼티 사용하기!
</Sections> | ||
|
||
<Button | ||
type="submit" |
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.
잊지 않고 type 설정해주기 좋다! 그런데 button의 type중에 submit은
태그에서 form data가 제출되는 버튼임을 명시하기 위함이라서type="button'
이 맞답니당
✨ 구현 기능 명세
🌱 기본 조건
.env
파일 사용하기🧩 기본 과제
[ 로그인 페이지 ]
/mypage/:userId
로 넘어갑니다. (여기서userId
는 로그인 성공시 반환 받은 사용자의 id)/signup
으로 이동합니다.[ 회원가입 페이지 ]
중복체크 버튼
회원가입 버튼
/login
으로 이동합니다.[ 마이 페이지 ]
/mypage/:userId
의 userId를 이용해 회원 정보를 조회합니다.🌠 심화 과제
[ 로그인 페이지 ]
createPortal
을 이용합니다.[ 회원가입 페이지 ]
비밀번호 확인
중복체크
생각과제
💎 PR Point
많이 쓰는 style 컴포넌트들은 style.js 에 모으고, 필요한 컴포넌트들은 import 해서 써줬습니다
💪 로그인 성공하면
/mypage/:userId
로 넘어가기-> navigate 사용!
navigate(`/mypage/${response.data.id}`);
💪 회원가입을 누르면
/signup
으로 이동하기-> Link 사용!
💪 중복체크 버튼
1. 필요한 변수를 선언하고,
2. axios.get하고 결과에 따라 buttonColor를 바꾸는 함수 handleIdisExist 선언
3. 함수 handleIdisExist는 중복체크 버튼을 눌렀을 때 동작한다. 함수에서 바꾼 buttonColor를 style에 적용
4. username이 달라질 때마다 buttonColor를 검정색으로 바꾸기 위해
useEffect
사용💪
/mypage/:userId
의 userId를 이용해 회원 정보를 조회-> useParam() 사용!
💪
createPortal
로 토스트 띄우기이때
toastMessage
는 로그인 실패했을 때의 메시지를 그대로 출력출력 3초 후에는 사라진다
🥺 소요 시간, 어려웠던 점
-� 중복확인 버튼 색깔을 바꾸는 데에서 시간을 많이 썻다... red/green 은 onClick로 black는 useEffect으로!
🌈 구현 결과물
Screen.Recording.2023-11-17.at.5.05.47.PM.mov
Screen.Recording.2023-11-17.at.5.07.34.PM.mov