const scrollRef = useRef<HTMLDivElement>(null);
const chatRef = useRef<HTMLDivElement>(null);
<div className="chat-list" ref={chatRef}>
{data &&
data.map((item: any, index: number) => {
return (
<div
className="chat-list__item"
key={`chat-list-${index}`}
ref={scrollRef} >
<img
src={item.avatar}
alt="uaer-avatar"
className="chat-list__item__avatar"/>
<div className="chat-list__item__nick"
{item.nickname}
</div>
<div
className="chat-list__item__text"
dangerouslySetInnerHTML={{ __html: item.content }}
></div>
<div className="chat-list__item__time">
{item.date.slice(11, 16)}
</div>
</div>
);
})}
</div>
const [bottom, setBottom] = useState(true);
chatRef.current?.addEventListener("scroll", scroll);
useEffect(() => {
if (bottom) {
const windowY: any = window.scrollY;
scrollRef.current?.scrollIntoView({
behavior: "auto",
block: "nearest",
});
window.scrollTo(0, windowY);
}
return () => {
chatRef.current?.removeEventListener("scroll", scroll);
};
}, [data]);
function scroll() {
let scrollTop: any = chatRef.current?.scrollTop;
let innerHeight: any = chatRef.current?.clientHeight;
let scrollHeight: any = chatRef.current?.scrollHeight;
if (Math.ceil(scrollTop + innerHeight) >= scrollHeight) {
setBottom(true);
} else {
setBottom(false);
}
}
element.scrollIntoView()
: scrollIntoView()
가 호출된 요소가 사용자에게 표시되도록 요소의 상위 컨테이너를 스크롤한다.
behavior
: 에니메이션을 정의 auto
, smooth
중 선택한다.
block
: 수직 정렬을 정의 start
, center
, end
, nearest
중 선택한다.
inline
: 수평 정렬을 정의 start
, center
, end
, nearest
중 선택한다.
scrollTop()
을통해 스크롤이 내려온 위치와 clientHeight()
를 통해 채팅이 보여지는 전체 화면의 높이를 더한 값이 scrollHeight()
를통해 얻은 스크롤 전체 페이지의 높이보다 같거나 크다면 스크롤이 맨 아래에 있다고 판단한다.
scrollTop() + clientHeight() >= scrollHeight()