문제 발생
- 채팅창을 구현하며 채팅을 입력했을 때 자동으로 채팅창 가장 하단으로 스크롤이 내려가도록 하는 기능을 구현하게 됨
document.getElementsByClassName('class').scrollTop
= document.getElementsByClassName('class').scrollHeight
- 스크롤 높이를 사용하여 조작하려고 시도했지만 가장 최신 채팅이 아닌 아래서 두번째 채팅을 기준으로 스크롤링됨
- → 콘솔을 찍어봤을 때 scrollTop 과 scrollHeight 의 값이 같게 적용되지 않았음. 하지만 이게 정확한 원인인지 파악할 수 없음
해결 과정
- DOM 을 직접 수정하는 방법을 적용할 수 없기 때문에, ref 를 사용하여 적용해보기로 함
- 전채 채팅을 감싸고 있는 ‘chat-list’ 에 boxRef 를 주고, 그 내부에 빈 div 태그를 만들어 scrollRef 를 주었음
- → boxRef 의 높이를 스크롤 높이와 비교하여 가장 아래에 있는 빈 div 태그 기준으로 스크롤이 내려갈 수 있도록 함.
export default function LiveDetail() {
// NOTE 스크롤 자동 이동
useEffect(() => {
if (chatListRef.current.offsetHeight < chatListRef.current.scrollHeight)
return scrollRef.current.scrollIntoView({ behavior: 'smooth' });
}, [chattings]);
return (
// ...
<div
className="chat-list"
style={{
height: `${
pinValue || pinValue === 0 ? 'calc(762px - 72px - 40px)' : 'calc(762px - 72px)'
}`,
}}
ref={chatListRef}
>
{chattings.map((c, index) => (
<Chatting
data={c}
chattings={chattings}
setStateChattings={setStateChattings}
key={index} // TODO
/>
))}
<div ref={scrollRef} />
</div>
// ...
)
}
⇒ offsetHeight 는 margin 이나 padding 을 고려한 높이. 하지만 테스트 해봤을 때 정상적으로 작동했음?
⇒ 조건문의 의미는 감싸고 있는 요소의 높이보다 채팅이 추가되어 늘어난 요소의 스크롤 높이가 높은 경우 가장 아래 두었던 스크롤 기준으로 스크롤됨. behavior 옵션으로 스크롤 애니메이션을 적용할 수 있음
⇒ 채팅이 생길 때마다 스크롤이 옮겨져야 하기 때문에 useEffect dependency 에 넣어줌