Front-end/React Native

React Native 역무한스크롤 구현하기 (채팅)

아지송아지 2022. 2. 12. 10:30

안녕하세요!

오늘은 저번 무한스크롤measure()에서 정리한 내용을 토대로 역무한스크롤을 구현해 보겠습니다.

역무한스크롤이란 아래에서 시작하여 위로 향하는 무한 스크롤을 의미합니다.

제가 지은 이름이라 정식 명칭은 다를 수도 있습니다.

 

이 기능은 주로 채팅에서 사용하였습니다.

 

이 기능의 핵심은 스크롤이 맨 끝에 갔을 때 콘텐츠의 사이즈가 늘어나도 스크롤 값을 기억하는 것입니다.

 

 

시작


// reverseInfinityScroll.js
import React, { useRef, useState } from 'react';
import { ScrollView, View } from 'react-native';

const R_InfinityScroll = ({children, onScrollEnd}) => {
    const chatScrollRef = useRef();
    const chatContentRef = useRef();
    const [totalChatHeight, setTotalChatHeight] = useState(0);

    const onScrollChat = e => {
        if(e.nativeEvent.contentOffset.y == 0){
            setTotalChatHeight(e.nativeEvent.contentSize.height);
            onScrollEnd();
        }
    }

    const onChangeChatSize = (e) => {
        chatContentRef.current.measure((x, y, width, height) => {
            chatScrollRef.current.scrollTo({x:0, y:height - totalChatHeight, animated: false});
        })
    }

    return(
        <ScrollView
            onScroll={onScrollChat}
            ref={chatScrollRef}
            onContentSizeChange={onChangeChatSize}
        >
            <View ref={chatContentRef}>
                {children}
            </View>
        </ScrollView>
    )
};

export default R_InfinityScroll;

위 코드가 풀 코드입니다.

차근차근 return 문안에서부터 하나씩 살펴보겠습니다.

 

1. <ScrollView>에 onScoll과 onContentSizeChange 이벤트를 넣어주었고 자식들을 <View>로 한번 감싸주었습니다.

  • onScroll 이란 스크롤을 할 때마다 일어나는 함수입니다.
  • onContentSizeChange란 콘텐츠의 사이즈가 변경되었을 때 일어나는 함수입니다.

제일 처음 {children}이 렌더링 됨에 따라 onContentChange가 반응할 것입니다.

 

 

2. onContentChange안에는 스크롤을 이동하는 로직을 작성합니다.

변경된 콘텐츠의 높이 값을 measure() 함수를 통하여 가져옵니다. (measure()은 이전 글에 설명이 있습니다.)

"변경된 높이 - 기존 높이"를 계산하여 스크롤을 이동시켜줍니다.

첫 렌더링의 경우에는 기존 높이가 0이기 때문에  스크롤은 제일 밑이 될 것입니다.

 

안쪽 view의 height를 가져온 이유는 <ScrollView>는 높이가 고정이고 자식요소들의 사이즈가 변경되기 때문입니다.

 

 

3. onScoll은 스크롤이 제일 상단으로 향했을 경우 조건문을 실행합니다.

조건문 안에서는 totalChatHeight에 현재 콘텐츠의 높이를 넣어줍니다.

그리고 props로 받은 onScrollEnd 함수를 실행시킵니다.

해당 함수는 이전 채팅을 서버에서 받아오는 등의 콘텐츠의 높이를 변화시키는 함수입니다.

 

4. 콘텐츠의 높이가 변했으니 다시 2번으로 가서 똑같은 로직을 실행합니다.

 

 

 

그림으로 한번 더 설명드리겠습니다.

1. 스크롤이 맨 위로 올라가면 콘텐츠의 전체 높이를 저장합니다.

 

2. 콘텐츠의 변경되면 변경된 높이에서 1번에서 저장된 높이를 빼줍니다.

 

정리하자면 스크롤 값을 저장하고 콘텐츠가 변경되면 그 위치로 이동하는 원리입니다.

 

 

 

다른 방법이 있거나 수정해야 할 부분 조언해 주시면 감사하겠습니다!