FlatList vs RecyclerListView비교결론RecyclerView설치기본dataProviderlayoutProviderrowRendererscrollTo 방법예시 코드트러블 슈팅
RecyclerListView
vsFlatList
비교글 : https://blog.logrocket.com/recyclerlistview-vs-flatlist-long-lists-react-native/ https://gorapaduck.tistory.com/entry/React-Native-ScrollView-vs-FlatList-vs-RecyclerListView
- 예제 코드 : https://snack.expo.dev/@myckhel/reactnative-recyclerlistview-hooks-example https://www.youtube.com/watch?v=V8qccBdjbhk
https://github.com/Flipkart/recyclerlistview/tree/master/docs/guides/samplecode ← 공식 예제코드
https://snack.expo.dev/@myckhel/reactnative-recyclerlistview-hooks-example ← 추천!
https://www.youtube.com/watch?v=V8qccBdjbhk ← 영상도 있고, repo도 있는데 코드 이해하기에 도움 많이 되었다.
- scrollTo 사용방법 : this._scrollViewRef.scrollTo is not a functionGithubthis._scrollViewRef.scrollTo is not a functionUpdatedMar 11, 2021
FlatList
vs RecyclerListView
비교
FlatList
는 네이티브 요소를 활용한다.
RecyclerListView
는JS
로만 구성된다.
FlatList
는 화면에 가까워지는 요소를 바깥에서 비동기로 렌더링 하고, 화면 밖으로 나가면 없애고 적절한 크기의 빈 공백으로 대체한다. (메모리를 효율적으로 사용하기 위함)
RecyclerListView
는 렌더링 해둔 것을 지우지 않고 재사용한다.
- 메모리 관점에서는
FlatList
가 더 좋을 수 있으나, 계산비용이 커서 렌더링 관점에서만 봤을 땐RecyclerListView
보다 성능이 떨어진다. FlatList
는 특히Android
의 경우에는 사용자가 빠르게 끝에서 끝으로 스크롤 시, 빈 공백이 보일 수도 있다.
결론
- 렌더링 관점에서만 보면
RecyclerListView
가 더 좋다.
- 메모리가 부족해서 효율적으로 사용해야 하는 경우에는
FlatList
가 좋다.
- :this._scrollViewRef.scrollTo is not a functionGithubthis._scrollViewRef.scrollTo is not a functionUpdatedMar 11, 2021
scrollTo
구현 방법
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;
트러블 슈팅

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가 먹여져 있어야 렌더링 가능하다.