FlatList에서 scrollToEnd 적용하기

Mingtorr·2021년 1월 23일
0
post-thumbnail

소켓을 이용한 채팅 페이지를 구축하면서 스크롤을 맨 밑으로 이동시켜야하는데 scrollToEnd가 먹히지 않는 문제에 직면했다. 이를 해결하기 위해 또 stackoverflow를 탐험하던 도중 해결책을 알아내어 정리한다.

scrollToEnd가 안되는 이유


우리의 scrollToEnd는 정상적으로 동작한다! 단지 렌더링 속도 때문에 맨 밑으로 이동하지 못할 뿐이다. Flatlist로 list를 불러오는 속도보다 scrollToEnd의 동작이 먼저 이루어지기 때문이다. 이를 해결하기 위해 componentDidMount 에 함수를 추가로 만들어 주기도 하고 Flatlist 저장 이후에 사용하기도 하는 등 여러가지 방법을 시도했으나 다 실패했었다 😥

첫번째 방법


하단 컴포넌트에게 prop으로 ScrollView.scrollToEnd 하는 함수를 넘기고 componentDidMount에서 400ms 뒤에 이 함수를 실행하는 방법이다.
즉, render가 끝난 이후에 동작하도록 settimeout을 걸어주는 방법이다.

  1. 생성자를 선언한다.
class Message extends PureComponent {
  constructor(props) {
    super(props);
    this.scrollViewRef = React.createRef();
  }
  1. 다음 함수를 선언하여 componentDidMount()에 넣어준다.
scrolltobottom = () => {
    setTimeout(() => {
      if (this.scrollViewRef !== null && this.scrollViewRef.current !== null) {
        this.scrollViewRef.current.scrollToEnd({animated: false});
      }
    }, 400);
  };

이 방법은 코드만 봐도 큰 문제점이 보인다. settimeout을 실행하기 때문에 인터넷 환경이 안좋아서 400ms보다 느리게 랜더링이 될 경우 함수가 동작하지 않는다. 또 빠르게 랜더링이 될 경우 400ms까지 기다려야 스크롤이 이동하는 큰 문제에 도달했다. 처음 에뮬레이터에서는 그럭저럭 만족스러운 수준을 보여주었으나 앱 추출 이후 테스트에서는 다른 방법을 찾아야만 했다.

두번째 방법


ScrollView의 onContentSizeChange를 이용하는 방법을 stackoverflow에서 찾았다.
scrollToEnd 정상적으로 동작하여 화면 랜더가 되는 동시에 맨 밑으로 이동한다.

<ScrollView
  style={{ display: "flex", flex: 0.97, backgroundColor: "white" }}
  ref="scrollView"
  onContentSizeChange={(width, height) => this.refs.scrollView.scrollTo({ y: height })}
>
  <FlatList
    ref={this.scrollViewRef}
    refreshing={this.state.refresh}
    onRefresh={this.func}
    data={this.state.arr} 
    renderItem={this.rendermessage}
  />
</ScrollView>;

이 방식이 통하는 이유는 ScrollView와 FlatList의 랜더링 방식 차이에 있다.
<ScrollView>는 한번에 렌더를 처리하게 된다. 반면 <FlatList>는 데이터가 너무 많을 경우 한번에 불러오는 것이 아닌 성능에 문제없을 만큼의 데이터를 조금씩 가져온다.

이 두 함수를 모두 사용해도 되는지 퍼포먼스 테스트는 좀 더 진행해야할 것 같다.

profile
츄르 값 벌기 위해 코딩하는 아키텍쳐

0개의 댓글