index가 필요할때는 순수 for문을 쓰자

BORA·2022년 4월 11일
0

코드 설명

이미지가 다 로드되고 나면, 이미지를 감싸고 있는 컴포넌트의 높이를 구해야 했다.
구한 높이값은 다른 컴포넌트(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 함수를 실행하도록 했다.

profile
코드치는 개발자가 아닌 생각하는 개발자!

0개의 댓글