-
Notifications
You must be signed in to change notification settings - Fork 20
React 강석준 sprint5 #74
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
React 강석준 sprint5 #74
The head ref may contain hidden characters: "React-\uAC15\uC11D\uC900-sprint5"
Conversation
/src를 @로 alias 설정
eslint와 충돌 해결 설정 및 tailwindcss plugin 적용
수정 전: 전체 상품에서 정렬 후 앞 부분을 베스트 상품으로 저장하는 방식 수정 후: 쿼리스트링으로 최소한의 데이터만 따로 불러와 저장하는 방식
|
스프리트 미션 하시느라 수고 많으셨어요. |
|
크으... 깃 로그가 언제나 깔끔하십니다 👍 |
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.
오호 ~ 린트를 적용하셨군요? 👍👍
| <Header /> | ||
| <div className="flex h-135 w-full items-end justify-center bg-blue-100"> | ||
| <PrimaryCard {...PRIMARY_CARDS[0]} /> | ||
| </div> | ||
| <div className="flex flex-col items-center pb-34.5"> | ||
| {FEATURE_CARDS.map((card) => ( | ||
| <div key={card.id} className="p-34.5"> | ||
| <FeatureCard {...card} /> | ||
| </div> | ||
| ))} | ||
| </div> | ||
| <div className="flex h-135 w-full items-end justify-center bg-blue-100"> | ||
| <PrimaryCard {...PRIMARY_CARDS[1]} /> | ||
| </div> | ||
| <Footer /> |
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.
Layout(Header, Footer)을 공통적으로 적용할 방법은 없을까요?
각 페이지 별로 Layout을 계속 불러오지 않고, react-router-dom을 이용해서 layout을 조건에 따라(로그인일 경우 X) 공통적으로 출력하는 방법이 없을까요?
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.
(추가로) react-routes-dom에서 레이아웃을 설정할 수 있어요. 😊
Consider: 판다마켓 초기에 작성한 로그인과 회원가입과 같은 페이지는 Header가 없는 디자인이예요. 지금과 같이 한다면 특정 페이지의 레이아웃을 조정하기 어려울거예요 !
Routes에서 element를 지정하여 중첩 레이아웃을 사용할 수 있으니 참고해서 설계해보세요 😊
tl;dr
// App.tsx
<Routes>
<Route path="/" element={<Main />}> // 중첩 라우팅
<Route path="user-management" element={<UserManagement />} />
<Route path="child-management" element={<ChildManagement />} />
</Route>
<Route path="/login" element={<Login />} />
</Routes>
// Main.tsx
<MainWrapper>
<MainMenu />
<Outlet /> // children과 같은 효과 ! ✨
</MainWrapper>| export const getItems = async ( | ||
| page, | ||
| pageSize, | ||
| orderBy = "recent", | ||
| keyword = null, | ||
| ) => { | ||
| const baseURL = "https://panda-market-api.vercel.app/products/"; |
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.
(제안) 해당 변수는 다른 api 함수에서 사용될 수도 있으므로 함수 바깥에 선언하는게 더욱 활용성이 좋겠군요 !
| export const getItems = async ( | |
| page, | |
| pageSize, | |
| orderBy = "recent", | |
| keyword = null, | |
| ) => { | |
| const baseURL = "https://panda-market-api.vercel.app/products/"; | |
| const baseURL = "https://panda-market-api.vercel.app/products/"; | |
| export const getItems = async ( | |
| page, | |
| pageSize, | |
| orderBy = "recent", | |
| keyword = null, | |
| ) => { | |
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.
(더 나아가서) base URL은 환경 변수에 저장하시는게 좋습니다!
환경 변수(Environment Variable):
process.env에 내장되며 앱이 실행될 때 적용할 수 있는 값입니다!
다음과 같이 적용할 수 있습니다:
// .env.development
REACT_APP_BASE_URL="http://localhost:3000"
// .env.production
REACT_APP_BASE_URL="http://myapi.com"
// 사용시
<a href={`${process.env.REACT_APP_BASE_URL}/myroute`}>URL</a>
왜 환경 변수에 저장해야 하나요?
개발(dev), 테스트(test), 실제 사용(prod) 등 다양한 환경에서 앱을 운영하게 되는 경우, 각 환경에 따라 다른 base URL을 사용해야 할 수 있습니다. 만약 코드 내에 하드코딩되어 있다면, 각 환경에 맞춰 앱을 배포할 때마다 코드를 변경해야 하며, 이는 매우 번거로운 작업이 됩니다. 하지만, 환경 변수를 .env.production, .env.development, .env.test와 같이 설정해두었다면, 코드에서는 단지 다음과 같이 적용하기만 하면 됩니다.
const apiUrl = `${process.env.REACT_APP_BASE_URL}/api`;
이러한 방식으로 환경 변수를 사용하면, 배포 환경에 따라 쉽게 URL을 변경할 수 있으며, 코드의 가독성과 유지보수성도 개선됩니다.
실제 코드 응용과 관련해서는 다음 한글 아티클을 참고해보세요! => 보러가기
| const params = new URLSearchParams({ | ||
| page: page, | ||
| pageSize: pageSize, | ||
| orderBy: orderBy, | ||
| }); |
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.
크으 ~ URLSearchParams를 사용하셨군요 ! 👍
쿼리를 작성할 때 정말 편하게 사용할 수 있도록 도와주지요 ~
| const response = await fetch(requrl, { | ||
| method: "GET", | ||
| }); |
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를 사용해보는건 어떨까요?(제안/선택)
fetch 모듈을 잘 만든다는 것은 어렵습니다. 다음 사항들을 고려해볼 수 있어요:
- 만약
get이 아닌 메써드(post,patch,delete등)일 경우는 어떻게 처리할 수 있을까요? query와body가 필요할 때는 어떻게 처리 할 수 있을까요?- 로그인 인가를 위한 토큰을 request 전에 자동으로 삽입할 수는 없을까요? (인증/인가를 자동으로 할 수 없을까요?)
- 처음 한 번에 Base URL을 지정할 수는 없을까요?
- Base URL을 사용하다가 타 Domain에 보내야 될 때는 어떻게 할 수 있을까요?
이 모든 요구사항들을 '잘 만든다는 것'은 어려워요. 따라서 이 모든걸 만들어진fetch모듈을 사용해보고 후에fetch모듈을 만들어 보는 것도 좋은 학습 방법이 될 수 있어요.
- Base URL을 사용하다가 타 Domain에 보내야 될 때는 어떻게 할 수 있을까요?
어떻게 세팅하면 될까? 🤔
instance를 만들어서 export를 하고 사용해보는 것 정도로 시도해보면 좋을 것 같아요. axios-instance 파일을 만들어서 instance를 생성하고 export한 후 사용해보는건 어떨까요?
다음과 같이 만들어볼 수 있어요:
const baseURL = process.env.NEXT_PUBLIC_LINKBRARY_BaseURL;
const instance = axios.create({
baseURL: baseURL,
headers: {
'Content-Type': 'application/json',
},
});
export default instance인가에 필요한 accessToken을 localStorage가 있다면 axios의 인터셉터를 활용할 수 있습니다 !
인터셉터는 혼자 해결해보시는 것을 권장드립니다. 혹시 모르시겠으면 다음 위클리 미션에 질문해주세요. 😊
사용 방법 🚀
사용 방법은 정말 간단해요. 다음과 같이 사용할 수 있습니다:
instance.get(`/user/${userId}`)딱 보니. 마이그레이션도 정말 쉽게 할 수 있겠죠? 😊
| try { | ||
| const res = await getItems(page, pageSize, orderBy); | ||
| setItems(res.list); | ||
| } catch (error) { | ||
| console.error("전체 상품 불러오기 실패", error); | ||
| } finally { | ||
| setItemsLoading(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.
크으 ~ 좋습니다. 에러 처리도 잘 해두셨군요 👍
| } catch (error) { | ||
| console.error("전체 상품 불러오기 실패", error); | ||
| } finally { |
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.
UI 계층에서 에러 발생 시 사용자 피드백도 함께 해주면 어떨까요?
| } catch (error) { | |
| console.error("전체 상품 불러오기 실패", error); | |
| } finally { | |
| } catch (error) { | |
| console.error("전체 상품 불러오기 실패", error); | |
| alert(error.message) | |
| } finally { |
설치 필요 없지.. 대부분의 브라우저와 디바이스에서 사용 가능하지...
alert는 정말 훌륭한 사용자 피드백 브라우저 API 입니다 !
| export const BREAK_POINTS = { | ||
| tablet: 768, | ||
| desktop: 1280, | ||
| }; |
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.
상수 선언 훌륭합니다 ! 👍👍
| desktop: 1280, | ||
| }; | ||
|
|
||
| function useResponsiveLayout({ onLayoutChange }) { |
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.
적절한 훅입니다 ! 👍👍
많이 사용될 것 같은데, 적절히 커스텀 훅을 만드셨군요 👍
|
어우 ~ 훌륭합니다 석준님. |
요구사항
기본
중고마켓
중고마켓 반응형
심화
결과 - 페이지 바로가기
멘토에게