개발자

리액트에서 최상단 더보기 기능에서 스크롤 문제

2024년 11월 08일조회 126

안녕하세요, 리액트로 채팅 기능 구현중입니다. 다름이 아니라 최상단 더보기 버튼을 클릭하면 api통신을 통해 새로운 메시지와 기존 메시지가 합쳐집니다. 그런데 리액트는 불변성이라서 컴포넌트를 새로 그릴때 더보기한 메시지가 먼저 그려지다 보니 스크롤이 계속 탑으로 변경되는데요,,, 모든 메시지가 다 그려지고 스크롤을 이동하면 되겠지만은, 근데 생각해보니 화면은 그대로 유지(스크롤 위치)가 되면서 업데이트 하는 방법은 없을까 계속 시도중인데 도저히 방법을 모르겠습니다.

이 질문이 도움이 되었나요?
'추천해요' 버튼을 누르면 좋은 질문이 더 많은 사람에게 노출될 수 있어요. '보충이 필요해요' 버튼을 누르면 질문자에게 질문 내용 보충을 요청하는 알림이 가요.
profile picture
익명님의 질문

답변 2

지민님의 프로필 사진

제가 이해한 바로는 일정 사이즈의 채팅을 읽고 기존 채팅데이터는 그 위치에 놔두고 최상단 더보기기능을 클릭하였을때 해당 스크롤 포지션에서 새로운 데이터를 호출하여 아래로 스크롤 하는것을 원한다 인데, 서버에서 일정사이즈마다 페이지네이션을 설정하였다는 가정하에 말씀드리자면 더보기를 클릭하였을때 readPage라는 상태변수가 있다면 setReadPage로 읽은 페이지까지 저장한다음 다 읽었을때 값을 하나씩 올리면서 호출하면 될것같네요? 만약 새로고침한 후에도 유지하고싶으시다면 react-query나 로컬스토리지로 캐싱하면 될것같구요. 아래는 비슷한 메커니즘으로 하나짜봤는데 이를 살펴보시는것도 괜찮을거같습니다.

1const loadMoreItems = useCallback(async () => {
2    if (isLoading || !hasMore || error) return; 
3    setIsLoading(true);
4    try {
5      if (cacheRef.current[page] && cacheRef.current[page] !== undefined ) {
6        setItems((prev) => [...prev, ...cacheRef.current[page]]);
7        setPage((prevPage:any) => prevPage + 1);
8        setIsLoading(false);
9        return;
10      }
profile picture

익명

작성자

2024년 11월 09일

제가 생각한 기능은 보통 더보기 누르면 해당 화면에서 멈추고 상위에 데이터들이 추가되고, 사용자가 위로 스크롤하면 내용을 볼 수 있지 않습니까? pc카톡에서 지난 대화글 보기와 같은 매커니즘입니다.

profile picture

익명

작성자

2024년 11월 09일

조금더 첨언을 하자면 스크롤이 왔다갔다 거리는게 아니라 리스트 영역만 커지고 스크롤을 고정이 되었으면 좋겠습니다.

지민님의 프로필 사진

지민

프론트엔드 개발자2024년 11월 09일

아. 그렇다면 데이터페칭 시점의 스크롤 포지션을 높이값으로 변환하고 데이터페칭 후 새로 추가된 스크롤height값에서 변환한 높이값을뺀 값을 current 스크롤탑 값으로 useEffect를 활용해서 리렌더링 하면서 진행하면 될것같네요. 더 좋을 방법이 있을것같긴한데 상향 무한스크롤 방식은 보통 포지션 유지가 까다로운 것에 속하다고 생각하여 그나마 제일 덜 복잡한 방법이라 생각해서 말씀드립니다.

profile picture

익명

작성자

2024년 11월 11일

네, 저도 상향 스크롤 때문에 지금 고민이 많습니다 ㅠ 더군다나 인피니티 스크롤링이여서 머리 아프네여

영훈님의 프로필 사진

혹시 해결하셨나요..? 저도 최근에 상향식 무한 스크롤 구현하면서 useRef로 데이터 페칭 이전 컴포넌트 높이 기억한 뒤 데이터 페칭 후 컴포넌트에서 빼주는 걸로 구현했는데 scroll behavior을 smooth로 설정해주니 스크롤이 최상단으러 갔다가 다시 내려 오는게 보여지더라구여ㅠㅠ 혹시 좋은 방법 알아내신게 있으시다면 조심스레 여쭤봐도 될까요,,

profile picture

익명

작성자

2024년 11월 23일

현재로썬 저도 그 방법이 최선이라 생각하고 있습니다.

영훈님의 프로필 사진

영훈

프론트엔드2024년 11월 23일

그렇군요,, 답변 감사합니다!

지금 가입하면 모든 질문의 답변을 볼 수 있어요!

현직자들의 명쾌한 답변을 얻을 수 있어요.

또는

이미 회원이신가요?

AI 답변
커리어리 AI 봇 프로필 이미지

커리어리 AI 봇

GPT가 달아주는 답변입니다.

2024년 11월 08일

화면의 스크롤 위치를 상태로 관리하고, 새로운 메시지가 추가될 때마다 이전 스크롤 위치를 유지하는 방향으로 생각해보실 수 있습니다. 예를 들어, React에서 useRef와 useEffect Hook을 사용하여 이를 구현할 수 있습니다. 먼저 아래와 같이 scrollRef라는 Ref를 생성합니다. ```javascript const scrollRef = React.useRef(null); ``` 그런 다음 useEffect 내에서 scrollRef의 current 속성을 이용하여 스크롤 위치를 제어합니다. 여기서 가장 중요한 것은 dependency array에 메시지 배열을 넣는 것입니다. 이렇게 하면 메시지 배열이 바뀔 때마다 useEffect가 실행되고, 따라서 스크롤 위치가 업데이트됩니다. ```javascript React.useEffect(() => { const { current } = scrollRef; if(current) { current.scrollTop = current.scrollHeight; // or any position you want } }, [messages]); // assuming `messages` is your array of messages ``` 이 방법은 단순히 맨 아래로 스크롤하는 경우입니다. 만약 특정 위치로 스크롤하려면 scrollTop 값을 조정하시면 됩니다. 다만 주의하실 점은 useRef는 컴포넌트가 리렌더링되도 값이 유지된다는 점입니다. 그래서 이전 스크롤위치를 계속해서 유지할 수 있습니다.

목록으로

지금 가입하면 모든 질문의 답변을 볼 수 있어요!