-
Notifications
You must be signed in to change notification settings - Fork 37
[김도균] Sprint11 #316
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
[김도균] Sprint11 #316
The head ref may contain hidden characters: "Next-\uAE40\uB3C4\uADE0-sprint11"
Conversation
1. 제네릭 타입을 활용한 axios return 명시 2. submit-commint 액션과 동일한 axios intercepts 활용
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 { AxiosError } from 'axios'; | ||
|
||
export async function submitArticle(formData: FormData, accessToken: string | null, refreshToken: string | null) { | ||
interface submitArticleResponse { |
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.
가급적이면 interface 나 type 의 이름의 시작은 대문자가 좀더 좋을것같아요~
SubmitArticleResponse 정도로요ㅎㅎ
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.
동작하는데엔 큰 문제는 없긴 하지만 가능하면 챙겨주면 좋아요ㅎㅎ!
id?: number; | ||
} | ||
|
||
export async function submitArticle(formData: FormData, accessToken: string | null, refreshToken: string | null): Promise<submitArticleResponse> { |
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.
formData로 데이터를 받으면 처음 이 함수를 보는 사람은 어떤 값을 포함해서 보내야 하는지 알기가 조금 어려워요ㅠ
차라리 email / password를 각각 받거나 SubmitArticleRequest 타입을 새로 정의해서 인자를 받고,
request 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.
멘토님 의견이 더 좋다고 생각합니다! 다음에 적용해보겠습니다.
try { | ||
const response = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/articles`, { | ||
method: 'POST', | ||
const response = await apiHelper.post<Article | ResponseWithAccessToken<Article>>('/articles', formDataObject, { |
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.
이렇게 명시적으로 타입을 지정해주는거 너무 좋아요...!
근데 response로 Article | ResponseWithAccessToken
가 오나요...?둘중 하나로만 올것같긴 해서... ResponseWithAccessToken로 오는경우는 어떤경우인지 싶어요
if ('accessToken' in response.data) { | ||
const newAccessToken = response.data.accessToken as string; | ||
result.accessToken = newAccessToken; |
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 { success: true, message: '게시글 생성이 완료되어 3초 후 페이지를 이동합니다.', id }; | ||
const result: submitArticleResponse = { success: true, message: '게시글 생성이 완료되어 3초 후 페이지를 이동합니다.', id: response.data.id }; | ||
if ('accessToken' in response.data) { | ||
const newAccessToken = response.data.accessToken as string; |
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.
근데 이경우엔 강제로 타입을 캐스팅 하지 않아도 값이 추론되지 않을까 싶긴 한데,
만약 추론이 된다면 따로 as를 사용해서 강제 캐스팅은 안해도 될것같아요...!
강제캐스팅은 좋은 패턴은 아니거든요ㅠ
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 관련 함수를 다 작성한 후에 적용해서 잠시 as로 놓았던 것 같습니다. 이 부분 참고하겠습니다!
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 router에 (...)
도 잘 활용하셨네요
헤더가 있는 부분이나 인증쪽을 묶은것도 그렇구요ㅎㅎ
interface Valid { | ||
email: string; | ||
password: string; | ||
isEmailValid: boolean; | ||
isPasswordValid: boolean; | ||
isValid: boolean; | ||
} |
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.
네이밍이 조금더 구체적이면 좋을것같아요...!
Valid 보단 LoginDataWithValid나 AuthData 같이요...ㅎㅎ
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 validateInputs = (email: string, password: string) => { | ||
const isEmailValid = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email); | ||
const isPasswordValid = password.length >= 8; | ||
const isValid = isEmailValid && isPasswordValid; | ||
return { isEmailValid, isPasswordValid, isValid }; | ||
}; | ||
|
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.
요건 아에 따로 컴포넌트 밖에 있어도 괜찮을것같은데요...?ㅎㅎ
의존성도 따로 없어서 utils로 빼도 되구요!
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 { isEmailValid, isPasswordValid, isValid }; | ||
}; | ||
|
||
const handleInputChange = (field: 'email' | 'password', value: string) => { |
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.
field를 email과 password로 추린거 좋네요!
이런식으로 원치않는 값이 넘어오는걸 빌드타임때 알 수 있도록 하는게 좋아요~
export const useAuthStore = create<Store>((set) => ({ | ||
accessToken: getLocalStorageItem('accessToken', ''), | ||
setAccessToken: (accessToken: string) => { | ||
localStorage.setItem('accessToken', accessToken); | ||
set((state) => ({ ...state, accessToken })); | ||
}, | ||
})); |
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.
zustand에서 자체적으로 localstorage에 저장해주는 기능을 지원해요ㅎㅎ!
https://zustand.docs.pmnd.rs/middlewares/persist#persist
persist인데, localstorage나 sessionstorage 등 저장소랑 동기화 해주니 이걸 사용하시는게 좀더 좋을것같아요!
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.
이러한 기능이 있는지 처음 알았네요. 말씀해주신 부분 참고하여 적용해보겠습니다!
요구사항
회원가입
로그인
메인
주요 변경사항
스크린샷
배포 웹사이트
멘토에게