RecyclerListView

부가 설명
FlatList 라고 생각하면 됨 (속도 측면에서 성능이 더 뛰어나다)
Tags
 

FlatList vs RecyclerListView

비교

  • FlatList는 네이티브 요소를 활용한다.
  • RecyclerListView는 JS로만 구성된다.
  • FlatList는 화면에 가까워지는 요소를 바깥에서 비동기로 렌더링 하고, 화면 밖으로 나가면 없애고 적절한 크기의 빈 공백으로 대체한다. (메모리를 효율적으로 사용하기 위함)
  • RecyclerListView는 렌더링 해둔 것을 지우지 않고 재사용한다.
  • 메모리 관점에서는 FlatList가 더 좋을 수 있으나, 계산비용이 커서 렌더링 관점에서만 봤을 땐 RecyclerListView 보다 성능이 떨어진다.
    • FlatList는 특히 Android의 경우에는 사용자가 빠르게 끝에서 끝으로 스크롤 시, 빈 공백이 보일 수도 있다.

결론

  • 렌더링 관점에서만 보면 RecyclerListView가 더 좋다.
  • 메모리가 부족해서 효율적으로 사용해야 하는 경우에는 FlatList가 좋다.
 

 
 

RecyclerView

설치

yarn add recyclerlistview
 

기본

- layoutProvider - dataProvider - rowRenderer
필수적으로 알아야 하는 부분은 위의 3가지 부분이다.

dataProvider

  • 이전 데이터와 현재 데이터가 어떻게 다른지 구분할 수 있는 방법 명시
  • 리스트에서 데이터로 활용할 상태값 설정
// 리스트에서 사용할 전체 데이터(배열) const [listData, setlistData] = React.useState(null); //Create the data provider and provide method which takes in two rows of data and return if those two are different or not. // 데이터가 바뀌었음을 판단할 수 있는 로직을 명시한다. const dataProvider = new DataProvider((r1, r2) => { return r1 !== r2; }); // ... fetch api ... useEffect(() => { if (isLoading === false && data !== undefined) { setlistData( dataProvider.cloneWithRows(data.data) ) // 리스트 데이터 설정 } }, [data, isLoading]);
 

layoutProvider

리스트가 사용할 화면의 레이아웃 정보를 제공한다.
⚠️
row에 들어갈 height와 width를 알아야 한다. 그렇지 않으면 안나오거나, 열끼리 컨텐츠가 겹쳐서 나온다거나 등의 현상이 생긴다.
// layoutProvier 예시 1 //Create the layout provider //First method: Given an index return the type of item e.g ListItemType1, ListItemType2 in case you have variety of items in your list/grid //Second: Given a type and object set the height and width for that type on given object //If you need data based check you can access your data provider here //You'll need data in most cases, we don't provide it by default to enable things like data virtualization in the future //NOTE: For complex lists LayoutProvider will also be complex it would then make sense to move it to a different file this._layoutProvider = new LayoutProvider( index => { if (index % 3 === 0) { return ViewTypes.FULL; } else if (index % 3 === 1) { return ViewTypes.HALF_LEFT; } else { return ViewTypes.HALF_RIGHT; } }, (type, dim) => { switch (type) { case ViewTypes.HALF_LEFT: dim.width = width / 2 - 0.0001; dim.height = 160; break; case ViewTypes.HALF_RIGHT: dim.width = width / 2; dim.height = 160; break; case ViewTypes.FULL: dim.width = width; dim.height = 140; break; default: dim.width = 0; dim.height = 0; } }, );
// layoutProvier 예시 2 const _layoutProvider = new LayoutProvider( index => 0, (type, dim) => { dim.width = dimensionsForScreen.width / 1; dim.height = dimensionsForScreen.width / 1; }, );
 

rowRenderer

FlatList에서 renderItem과 같은 녀석이다.
단일 요소를 어떻게 표현할 건지를 명시한다.
const renderList = (type, animeData, index) => { const animeObj = animeData.entry; return ( <View> <TouchableOpacity activeOpacity={0.9}> <FastImage source={{ uri: animeObj.images.jpg.image_url, priority: FastImage.priority.high, }} style={styles.tinyLogo}> <View style={styles.overlay} /> <View style={styles.pushTextToBottom}> <Text style={styles.textStyles}>{animeObj.title}</Text> </View> </FastImage> </TouchableOpacity> </View> ); }; ... <RecyclerListView ... rowRenderer={(type, animeData, index) => renderList(type, animeData, index) } ... />
 

scrollTo 방법

const listView = useRef(); const scrollToTop = () => { listView.current?.scrollToOffset(0, 0, true); // (x, y, animated:boolean) }; <RecyclerListView ref={listView}...
 

예시 코드

import React, {useEffect, useState} from 'react'; import {Dimensions} from 'react-native'; import {DataProvider, LayoutProvider, RecyclerListView} from 'recyclerlistview'; import {GroupedRectList} from './GroupedRectList'; const {width} = Dimensions.get('window'); const GroupNames = [ 'one', 'two', 'three', 'four', 'five', 'one', 'two', 'three', 'four', 'five', 'one', 'two', 'three', 'four', 'five', 'one', 'two', 'three', 'four', 'five', 'one', 'two', 'three', 'four', 'five', 'one', 'two', 'three', 'four', 'five', 'one', 'two', 'three', 'four', 'five', 'one', 'two', 'three', 'four', 'five', 'one', 'two', 'three', 'four', 'five', 'one', 'two', 'three', 'four', 'five', 'one', 'two', 'three', 'four', 'five', 'one', 'two', 'three', 'four', 'five', 'one', 'two', 'three', 'four', 'five', 'one', 'two', 'three', 'four', 'five', 'one', 'two', 'three', 'four', 'five', 'one', 'two', 'three', 'four', 'five', 'one', 'two', 'three', 'four', 'five', 'one', 'two', 'three', 'four', 'five', 'one', 'two', 'three', 'four', 'five', 'one', 'two', 'three', 'four', 'five', ]; export const Recycle = () => { const [listData, setListData] = useState<string[]>([]); //Create the data provider and provide method which takes in two rows of data and return if those two are different or not. const dataProvider = new DataProvider((r1, r2) => { return r1 !== r2; }).cloneWithRows(listData); const thisLayoutProvider = new LayoutProvider( _index => 0, (type, dim) => { dim.width = width; dim.height = width; }, ); const rowRenderer = (type, data, index, extendedState) => { return <GroupedRectList title={data} />; }; useEffect(() => { setListData(GroupNames); }, []); return ( <RecyclerListView layoutProvider={thisLayoutProvider} dataProvider={dataProvider} rowRenderer={rowRenderer} style={{flex: 1}} /> ); };
import React from 'react'; import {View} from 'react-native'; import {Recycle} from './src/components/Recycle'; const App = () => { return ( <View style={{flex: 1}}> {/* 가장 바깥 영역 flex:1 필수 */} <Recycle /> </View> ); }; export default App;
 

트러블 슈팅

notion image
ERROR LayoutException: RecyclerListView needs to have a bounded size. Currently height or, width is 0.Consider adding style={{flex:1}} or, fixed dimensions, js engine: hermes
맨 바깥 영역 등 flex가 먹여져 있어야 렌더링 가능하다.