이미지가 다 로드되고 나면, 이미지를 감싸고 있는 컴포넌트의 높이를 구해야 했다.
구한 높이값은 다른 컴포넌트(Sidebar
)에 props로 넘겨준다.
interface IProps {
targetCamp: ICampDetail;
}
const ContentsSection = ({ targetCamp }: IProps) => {
const containerRef = useRef() as React.MutableRefObject<HTMLElement>;
const imgRef = useRef() as React.MutableRefObject<HTMLElement>;
const [height, setHeight] = useState<number>(0);
// 문제 함수
const onloadImages = useCallback(() => {
const imgs = imgRef.current.querySelectorAll('img');
const len: number = imgs.length;
let count: number = 0;
for(let img of imgs) {
img.onload = () => {
count++;
if(count === len) getHeight();
}
}
}, []);
const getHeight = () => {
const newHeight = containerRef.current.clientHeight;
setHeight(newHeight);
};
useEffect(() => {
targetCamp && onloadImages();
window.addEventListener('resize', getHeight);
return () => {
window.removeEventListener('resize', getHeight);
};
}, [onloadImages, targetCamp]);
return (
<Container ref={containerRef}>
{targetCamp.images.map((img, index) => (
<img key={index} src={img} />
))}
<Sidebar height={height}/>
</Container>
)
};
export default ContentsSection;
이 코드에서,
Function declared in a loop contains unsafe references to variable(s) 'count', 'count'.
라는 ESLint 오류가 떴는데, 루프 안에서 count 변수가 안전하지 않다는 내용이었다.
ESLint 공식문서를 찾아보니, 예상대로 작동하지 않을 수 있는 코드 부분을 강조하기 위해 발생하며 언어 작동 방식에 대한 오해를 나타낼 수 있다고 한다. 즉, 루프 내에서 함수를 작성하면 코드가 문제 없이 실행될 수는 있지만 일부 상황에서는 예기치 않게 작동할 수 있으므로 주의를 준 것 같다.
const ContentsSection = ({ targetCamp }: IProps) => {
const containerRef = useRef() as React.MutableRefObject<HTMLElement>;
const imgRef = useRef() as React.MutableRefObject<HTMLElement>;
const [height, setHeight] = useState<number>(0);
// 리팩토링 후
const onloadImages = useCallback(() => {
const imgs = imgRef.current.querySelectorAll('img');
for (let i = 0; i < imgs.length; i++) {
imgs[i].onload = () => {
if (i === imgs.length - 1) getHeight();
};
}
}, []);
const getHeight = () => {
const newHeight = containerRef.current.clientHeight;
setHeight(newHeight);
};
useEffect(() => {
targetCamp && onloadImages();
window.addEventListener('resize', getHeight);
return () => {
window.removeEventListener('resize', getHeight);
};
}, [onloadImages, targetCamp]);
return (
<Container ref={containerRef}>
{targetCamp.images.map((img, index) => (
<img key={index} src={img} />
))}
<Sidebar height={height}/>
</Container>
);
};
export default ContentsSection;
for of
문을 for
문으로 바꿔서, 리팩토링을 진행했다.
index
가 필요한 상황이어서, 굳이 for of
를 써서 count
변수를 만들지 않아도 되기 때문이었다. 대신 index
는 0부터 시작하기 때문에, 총 길이에서 하나를 빼준 값과 index
값이 같으면, getHeight 함수를 실행하도록 했다.