Nextjs React 채팅창 스크롤 아래로 보내는 방법 scrollIntoView

next + firebase 조합으로 채팅창을 작업하던중에 , 새로운 메세지를 입력할 때 마다 가장 아래로 스크롤을 보내는 기능이 필요했다.

 

useRef를 이용해 DOM에 접근해서 scrollIntoView()를 이용해 입력때 마다 아래로 이동하게 하려고 했는데..

 

아무리해도 작동을 하지 않았다.

 

처음 내가 작성했던 코드는 아래와 같다. (스타일,구조 완성된 코드아님 주의)

 

<ul className='message-list' ref={messageRef}>
                    {
                        messageList?.docs.map((e, i) => {
                            const data = e.data()
                            const date = data.createdAt?.seconds ? formatDate(new Date(data?.createdAt.seconds * 1000)) : null

                            return (
                                <li key={i}>
                                    <Avatar style={{ width: 32, height: 32, display: 'block' }} icon={<UserOutlined />} />
                                    <div className='content-container'>
                                        <div>
                                            <span className='user-name'>{data.userName}</span>
                                            <span>{date}
                                            </span>
                                        </div>
                                        <div className='messasge-box'>
                                            {data.text}
                                        </div>
                                    </div>
                                </li>

                            )
                        })
                    }

</ul>

 

ul 태그에 y 축 오버플로우를 스크롤로 설정했다.

이 경우에는 scrollIntoView는 동작하지 않았고 , scrollTo로 높이를 계산해서 이동시키는것은 동작했으나, 처음 렌더링에만 되었고

useEffect 디펜던시에 추가했음에도 메세지가 추가되었을때는 되지 않았다.

 

div 태그로 감싸주어야 된다는 글을 보고 ul 태그를 div로 감싼 후 해봤지만 여전히 되지 않았다.

 

깃헙에서 react chat관련 레포지토리를 찾아 보던 중, 해당 방법을 발견하고 코드에 적용 해봤다.

 

 <div style={{ overflowY: 'scroll', height: 'calc(40vw - 70px)' }}>
                <ul className='message-list' >
                    {
                        messageList?.docs.map((e, i) => {
                            const data = e.data()
                            const date = data.createdAt?.seconds ? formatDate(new Date(data?.createdAt.seconds * 1000)) : null

                            return (
                                <li key={i}>
                                    <Avatar style={{ width: 32, height: 32, display: 'block' }} icon={<UserOutlined />} />
                                    <div className='content-container'>
                                        <div>
                                            <span className='user-name'>{data.userName}</span>
                                            <span>{date}
                                            </span>
                                        </div>
                                        <div className='messasge-box'>
                                            {data.text}
                                        </div>
                                    </div>
                                </li>

                            )
                        })
                    }

                </ul>
                <div ref={messageRef} />
            </div>

 

ul을 div로 감싸고 ul 밑에 div태그를 생성하여 그 div에 ref컨트롤을 하니 잘 작동했다 !!!

 

 

scrollIntoView 옵션은 이곳에서 확인 할 수 있다.

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

 

Element.scrollIntoView() - Web APIs | MDN

The Element interface's scrollIntoView() method scrolls the element's parent container such that the element on which scrollIntoView() is called is visible to the user.

developer.mozilla.org