-
Notifications
You must be signed in to change notification settings - Fork 39
[김진선] refactor/sprint5 #173
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
[김진선] refactor/sprint5 #173
Conversation
… unified pagination and sort logic
addiescode-sj
left a comment
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 객체 사용하기
- 메모리 누수 방지를 위해 AbortController + useRef 사용하기
|
|
||
| export async function fetchPaginatedProducts({ page = 1, pageSize = 10 } = {}) { | ||
| const res = await fetch( | ||
| `${BASE_API_URL}/products?page=${page}&pageSize=${pageSize}` |
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 객체 사용해서 여러개의 파라미터를 관리해보는 방법으로 바꾸면, 쿼리 스트링의 파싱, 조작, 인코딩 등의 작업을 간편하게 처리할 수 있으면서도 실수를 줄일 수 있겠죠? :)
아래 아티클 참고해보세요!
참고
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.
해당 파일이 공용으로 쓰이는 파일이 아니라면 사용하는 입장에서 가장 가깝게 (찾기 쉽게) 유지해주시는 것이 좋습니다.
pages > Items > constants > products.js 로 옮겨보시는게 어떨까요?
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 BestProducts from "./components/BestProducts/BestProducts"; | ||
| import AllProducts from "./components/AllProducts/AllProducts"; | ||
| import { BEST_PRODUCTS_PER_DEVICE,ALL_PRODUCTS_PER_DEVICE } from "../../constants/products"; | ||
| import { TITLE_ALL_PRODUCTS_COMP,TITLE_BEST_PRODUCTS_COMP } from "../../constants/titles"; |
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.
5,6 번 라인 사이 공백 한칸 띄워줄까요?
| const updateProducts = async () => { | ||
| const data = await fetchProducts(); | ||
| const sorted = data.sort((a, b) => b.favoriteCount - a.favoriteCount); | ||
| const limit = getLimitFromWindowWidth( | ||
| itemsPerDevice.desktop, | ||
| itemsPerDevice.tablet, | ||
| itemsPerDevice.mobile | ||
| ); | ||
| setBestProducts(sorted.slice(0, limit)); | ||
| }; |
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.
해당 코드의 메모리 누수를 방지하려면 항상 이전 요청을 취소하고 새 요청을 시작하도록 만들어주는게 좋은데요!
아래 예시처럼 AbortController와 useRef를 사용해보면 어떨까요?
// 컴포넌트 내부
function BestProducts({ title, itemsPerDevice }) {
const abortControllerRef = useRef(null);
const updateProducts = useCallback(async () => {
try {
// 이전 요청이 있다면 취소
if (abortControllerRef.current) {
abortControllerRef.current.abort();
}
// 새로운 AbortController 생성
abortControllerRef.current = new AbortController();
const data = await fetchProducts({ signal: abortControllerRef.current.signal });
const sorted = data.sort((a, b) => b.favoriteCount - a.favoriteCount);
const limit = getLimitFromWindowWidth(
itemsPerDevice.desktop,
itemsPerDevice.tablet,
itemsPerDevice.mobile
);
setBestProducts(sorted.slice(0, limit));
} catch (error) {
if (error.name === 'AbortError') {
// 요청이 취소된 경우 무시
return;
}
// 다른 에러 처리
console.error('Error fetching products:', error);
}
}, [itemsPerDevice]);
...
}이렇게 하면 두가지 동작을 보장할수있어요 :)
- 새로운 요청이 시작될 때 이전 요청을 취소합니다.
- 컴포넌트가 언마운트될 때 진행 중인 요청을 취소합니다.
질문에 대한 답변
리뷰를 위해서라면 주석보다는 PR 올리신 후 코멘트로 더 체크 원하시는 부분 라인 선택해서 달아주시면 좋습니다! :) |
주요 변경사항
멘토에게