카테고리 없음

[React]리스트에 아이템 추가하고, 최신 아이템으로 스크롤 이동해보자.

아보카도 있었어! 2023. 8. 5. 23:11

투두리스트에 스크롤이 생겼을 때 할 일을 추가하면 추가한 일로 스크롤이 이동하여 사용자가 방금 추가한 할 일을 바로 확인할 수 있도록 하고 싶었다.

 

1. useEffect 사용

처음엔 useLayoutEffect() hook 으로 '새로 추가된 아이템이 반영된 리스트의 높이를 미리 계산해야 하지 않을까' 했지만, useEffect() hook 만 사용해도 문제없이 잘 동작했기 때문에, useEffect() hook 을 사용하였다.

할 일이 추가되거나, 삭제될 때 동작이 달라야 하므로 prop으로 내려받고 있는 data의 길이를 dependency로 설정하였다.

 

2. useRef 사용

사용자가 할 일을 추가하거나 삭제할 때 할 일을 렌더링하고 있는 리스트의 길이가 변화하므로, useRef로 해당 DOM에 접근할 수 있도록 연결해 주었다.

 

3. elem.scrollTop 프로퍼티 조작

🔗 https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollTop

  • scrollTop : 세로 스크롤바에 가려져 보이지 않는 '위쪽' 컨텐츠의 높이
  • scrollHeight : 세로 스크롤바에 가려진 부분을 포함하는 콘텐츠 영역 안쪽 전체의 높이

스크롤의 가장 최하단에 스크롤을 위치 시키기 위해, scrollTop을 scrollHeight과 동일하도록 맞춰주었다.

 

구현

코드

export default function TodoList({ data }) {
	const [listHeight, setListHeight] = useState(0); // 이전 렌더링의 list 값을 기억할 변수를 state로 관리
    
    	const listRef = useRef(null);

  	useEffect(() => {
    	if (listRef.current) {
      	const height = listRef.current.scrollHeight;
	
    	// data가 추가될 때만 스크롤 이동하도록
      	if (listHeight < height) {
        	listRef.current.scrollTop = listRef.current.scrollHeight;
      	}
      	return setListHeight(height);
    	}
	  }, [data.length]);
  
  return (
      <ul className="TodoList" ref={listRef}>
          Todos
      </ul>
  )
}

 

가장 간단하게 단순히 스크롤을 최하단으로 이동시키는 것으로 구현하긴 했지만, 다른 방법으로도 구현할 수 있을 것 같다. 추가되는 요소가 리스트의 가장 마지막 요소일 테니 해당 요소에 ref를 연결해서 화면에 보이도록 elem.scrollIntoView() 메서드를 활용해도 될 것 같다는 생각이 들었다. 이외에도 좀더 요소에 집중해서 해당 요소를 기준으로 스크롤을 조작하는 방법이 있을 것 같기는 한데 좀더 공부가 필요할 것 같다.

 

참고문서

https://ko.javascript.info/size-and-scroll#ref-497