-
Notifications
You must be signed in to change notification settings - Fork 3
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: 식품 이미지(SuspendedImg)에 lazy loading 적용 #529
Conversation
img.src = src!; | ||
}), | ||
...(staleTime == null ? {} : { staleTime }), | ||
...(cacheTime == null ? {} : { cacheTime }), | ||
enabled: enabled && Boolean(src), | ||
enabled: lazy ? isIntersected : true, |
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.
lazy loading의 경우 돔이 감지되었을 때 이미지 요청을 하도록 변경(버그 수정)하였습니다
interface SuspendedImgProps extends ComponentPropsWithoutRef<'img'> { | ||
staleTime?: number; | ||
cacheTime?: number; | ||
enabled?: 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.
유용할 것 같지 않은 속성을 제거하였습니다
}; | ||
|
||
export default SuspendedImg; | ||
export default memo(SuspendedImg); |
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.
memo를 적용했습니다
@@ -13,7 +13,7 @@ const FoodItem = (foodItemProps: FoodItemProps) => { | |||
return ( | |||
<FoodItemWrapper to={`pet-food/${id}`}> | |||
<FoodImageWrapper> | |||
<FoodImage src={imageUrl} alt="Food image" /> | |||
<FoodImage src={imageUrl} alt="Food image" lazy /> |
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.
누락됐던 lazy 속성을 추가했습니다
@@ -8,7 +8,7 @@ interface UseIntersectionObserverOptions<T extends HTMLElement> { | |||
export const useIntersectionObserver = <T extends HTMLElement>( | |||
options?: UseIntersectionObserverOptions<T>, | |||
) => { | |||
const localRef = useRef<T>(null); | |||
const localRef: MutableRefObject<T | null> = useRef<T>(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.
ref.current 수정이 필요하여 MutableRefObject
로 타입을 지정하였습니다
if (isIntersected && targetRef.current && !targetRef.current.src && src) { | ||
targetRef.current.src = src; | ||
} |
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.
!targetRef.current.src
: 이미지 중복 다운을 방지(이미지 다운 실패 시)하기 위하여 추가한 조건입니다
src
: src 속성에 올바르지 않은 경로(ex. undefined)가 추가되는 것을 방지하기 위하여 추가한 조건입니다
const callbackRef = useCallback((instance: HTMLImageElement | null) => { | ||
targetRef.current = instance; | ||
|
||
if (!ref) return; | ||
|
||
// eslint-disable-next-line no-param-reassign | ||
typeof ref === 'function' ? ref(instance) : (ref.current = instance); | ||
}, []); |
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.
외부 ref와 내부 ref(targetRef)에 동일한 돔을 할당하고자 img 엘리먼트에 callbackRef를 삽입하는 방식으로 변경하였습니다.
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.
LazyImg
는 외부에서 ref를 주입받을 수 있는데요!
내부적으로는 lazy loading을 위해 useIntersectionObserver
에서 반환된 targetRef
를 사용하고 있어요! (옵저빙 되고 있는 ref)
외부 ref를 신경쓰지 않을 땐 targetRef를 img 엘리먼트에 바로 주입해도 문제가 없었지만 외부 ref가 주입될 수 있는 경우
ref는 콜백 함수 혹은 refObject일 수 있습니다!
각 경우의 수에 대비하고 외부 ref에 img 엘리먼트를 제공함과 동시에 targetRef에도 ref와 동일한 img 엘리먼트를 할당하기 위해 커밋 페이즈에 돔과 함께 실행되는 callbackRef 방식을 사용하여 각 ref에 동일한 img 엘리먼트를 할당하였습니다!
}); | ||
|
||
const callbackRef = useCallback((instance: HTMLImageElement | null) => { | ||
targetRef.current = instance; |
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.
targetRef를 통해 img 엘리먼트에 접근하고 이미지 다운로드를 조작합니다
if (!ref) return; | ||
|
||
// eslint-disable-next-line no-param-reassign | ||
typeof ref === 'function' ? ref(instance) : (ref.current = instance); |
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.
외부 ref가 callbackRef인 경우 그대로 실행시키고, 아닌 경우 외부 ref에 img 엘리먼트를 할당합니다
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.
고생했어요~
📄 Summary
SuspendImg
의 lazy loading 기능을LazyImg
를 활용하여 구현LazyImg
가 callbackRef를 받을 수 있도록 보강🙋🏻 More