[React Native] FlatList 내에 FlatList 중첩 사용하기

aborile·2023년 5월 20일
0

React Native

목록 보기
4/8
post-thumbnail

RN에서 스크롤 영역이 필요하다면 이를 구현하는 방법에는 ScrollView를 사용하는 방법과 FlatList를 사용하는 방법이 있다. ScrollView의 경우에는 한번에 전체 영역을 렌더링하고, FlatList는 화면에 보일 만큼, 또는 설정한 수 만큼만 초기 렌더링한다는 특징이 있다. 이러한 특성에 맞추어 각 목적에 따라 필요한 컴포넌트를 사용하여 구현을 하면 된다.

그러나 불행히도, 때로는 구현 요구사항이 훨씬 복잡할 때가 있다. 전체 스크롤 영역과 별개로 그 안에서 일부 영역만 추가로 스크롤이 필요한 구현 사항의 경우 어떨까?
ScrollView 안에 ScrollView를 넣는다면 쉽게 해결되겠지만, (안드로이드의 경우 nestedScrollEnabled 옵션 필요) ScrollView 영역에 FlatList를 넣으려 하는 경우 약간의 불행이 시작된다.

VirtualizedLists should never be nested inside plain ScrollViews with the same orientation because it can break windowing and other functionality - use another VirtualizedList-backed container instead.

위와 같은 에러를 한번 쯤은 마주해 본 사람이 꽤 많을 것이다.

이는 단순하게 FlatListListHeaderComponent, ListFooterComponent 옵션을 잘 사용하거나, FlatList 안에 FlatList를 넣도록 수정하면 해결되는 오류이기는 하다. 나는 주로 후자의 방식으로 개발해 왔다.

<FlatList
  data={[]}
  renderItem={null}
  ListEmptyComponent={
    <>
      <View>
        <Text>Something to add above...</Text>
      </View>
    
      <FlatList data={data} {...} />
    
      <View>
        <Text>Something to add below...</Text>
      </View>
    </>
  }
/>

그러다가 필요할 때마다 일일이 위와 같이 코드를 작성하는 게 귀찮아져, 어느 날 그냥 공통 컴포넌트를 하나 작성했다. 기존 ScrollView처럼 원하는 컴포넌트를 children으로 넘길 수 있게 하고, 내가 개발하던 프로젝트의 경우 Animated FlatList를 사용하거나 FlatList 내에 ref 옵션을 넘겨야하는 경우가 많았어서 이를 고려한 옵션까지 추가해 두었다.

import { memo, ReactNode, RefObject } from "react";
import { Animated, FlatList, VirtualizedListWithoutRenderItemProps } from "react-native";

interface FlatListScrollViewProps {
  children?: ReactNode;
  isAnimated?: boolean;
  scrollRef?: RefObject<FlatList>;
}
/**
 * ScrollView 안에 FlatList를 넣어야할 때에 대신 사용할 컴포넌트
 */
function FlatListScrollView<T>({
  children,
  isAnimated,
  scrollRef,
  ...props
}: FlatListScrollViewProps & VirtualizedListWithoutRenderItemProps<T>) {
  if (isAnimated) {
    return (
      <Animated.FlatList {...props} ref={scrollRef} data={[]} renderItem={null} ListEmptyComponent={<>{children}</>} />
    );
  }

  return <FlatList {...props} ref={scrollRef} data={[]} renderItem={null} ListEmptyComponent={<>{children}</>} />;
}

export default memo(FlatListScrollView);

시행착오

FlatList 내에 일정한 height를 가진 FlatList를 같은 방향으로 스크롤하도록 넣는 경우, nested scroll이 제대로 동작하지 않는다. 검색해 보면 비슷한 이슈의 글들을 어렵지 않게 찾을 수 있는데, 대부분 react-native-gesture-handler 라이브러리의 FlatList를 사용하거나, ScrollView로 변경해서 해결했다고 한다.

때문에 나는 다른 방향 스크롤이 들어가는 경우에만 위와 같은 코드를 사용하고, 같은 방향 스크롤이 필요한 경우에는 상황에 따라 FlatList 또는 ScrollView root 내에 ScrollView를 사용하였다.

profile
기록하고 싶은 것을 기록하는 저장소

0개의 댓글