FlatList 사용 예제
리액트 네이티브에서 배열 안에 들어있는 원소들을 보여줄때 FlatList 컴포넌트를 사용하기도 한다.
아래 예제 코드에 설정값을 보며 설명을 정리해보겠다.
import React from 'react';
import {View, Text, FlatList, StyleSheet, Image} from 'react-native';
function FlatListTest() {
const todos = [
{id: 1, text: '샤워하기', done: true},
{id: 2, text: '기술 공부하기', done: false},
{id: 3, text: '독서하기', done: false},
];
return (
<FlatList
style={styles.list}
data={todos}
ItemSeparatorComponent={() => <View style={styles.separator} />}
renderItem={({item}) => (
<View style={styles.item}>
<View style={[styles.circle, item.done && styles.filled]}>
{item.done && (
<Image
source={require('../assets/icons/check_white/check_white.png')}
/>
)}
</View>
<Text style={[styles.text, item.done && styles.lineThrough]}>
{item.text}
</Text>
</View>
)}
keyExtractor={item => item.id.toString()}
/>
);
}
const styles = StyleSheet.create({
list: {
flex: 1,
},
separator: {
backgroundColor: '#e0e0e0',
height: 1,
},
item: {
flexDirection: 'row',
padding: 16,
alignItems: 'center',
},
circle: {
width: 24,
height: 24,
borderRadius: 12,
borderColor: '#26a69a',
borderWidth: 1,
marginRight: 16,
},
text: {
flex: 1,
fontSize: 16,
color: '#212121',
},
filled: {
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#26a69a',
},
lineThrough: {
color: '#9e9e9e',
textDecorationLine: 'line-through',
},
});
export default FlatListTest;
FlatList 컴포넌트에 ItemSeparatorComponent 속성은 반복되는 컴포넌트들 사이에 구분선을 설정한다.
<FlatList ... ItemSeparatorComponent={() => <View style={styles.separator} />} />
data 속성에 배열 데이터를 설정하면 renderItem 함수를 통해 배열 안의 각 원소 데이터를 가리키는 뷰를 보여줄 수 있다.
<FlatList ... data={todos} renderItem={({item}) => ( ... )} />
리스트를 렌더링할 때는 고유값이 꼭 필요하다. keyExtractor 속성은 각 항목 데이터 고유의 값을 설정해준다.
만약 고유의 값이 없으면 배열의 index값을 사용하기도 하는데 이때는 변동사항이 생기면 리렌더링을 비효율적으로 업데이트 하므로 주의해야 한다. 참고로 고유값은 문자열 형태여야 하므로 숫자일때는 toString 함수를 호출해 문자열로 변환해서 설정해야 한다.
<FlatList ... keyExtractor={item => item.id.toString()} />
위 코드에 실행 결과는 아래와 같다.
스크롤을 감지해 이벤트 적용 1
FlatList에서 스크롤이 바닥에 닿았을 때 어떤 작업이 하고 싶다면 onEndReached 함수와 onEndReachedThreshold 값을 설정하면 된다.
<FlatList ...
onEndReached={(distanceFormEnd) => {
console.log("바닥과 가까워졌어요!");
}}
onEndReachedThreshold={0.85} />
이렇게 하면 콘텐츠의 85%까지 스크롤했을때 onEndReached 함수가 호출된다.
스크롤로 더 많은 정보를 불러오는 무한 스크롤링을 구현할 때 이 Props를 사용하면 유용하다.
하지만 이 속성은 스크롤을 내렸을 때는 감지가 가능하지만 스크롤을 올릴때는 감지되지 않는다.
스크롤을 감지해 이벤트 적용 2
onEndReached와 onEndReachedThreshold Props는 스크롤을 올릴때 감지되지 않는다.
스크롤을 올릴때 감지가 필요하다면 onScroll 이벤트를 사용하면 된다.
onScroll 이벤트를 사용하면 콘텐츠의 전체 크기와 스크롤의 위치를 알아낼 수 있다.
const onScroll = (e) => {
const {contentSize, layoutMeasurement, contentOffset} = e.nativeEvent;
console.log({contentSize, layoutMeasurement, contentOffset});
};
<FlatList ... onScroll={onScroll}/>
위처럼 사용하게 되면 콘텐츠를 스크롤 할 때마다 콘솔에 콘텐츠의 크기 정보가 출력될 것이다.
contentSize.height는 FlatList 내부의 전체 크기를 나타내고, layoutMeasurement.height는 화면에 나타난 FlatList의 실제 크기를 나타낸다. contentOffset.y는 스크롤할 때마다 늘어나는 값인데, 스크롤이 맨 위에 있을 때는 0이고, 스크롤이 맨 아래에 있을 때는 contentSize.height - layoutMeasurement.height를 계산한 값이다.
따라서 contentSize.height - layoutMeasurement.height - contentOffset.y가 0에 가까워 진다면 FlatList의 스크롤이 바닥에 가까워지는 것이라고 이해하면 된다.
const onScroll = (e) => {
const {contentSize, layoutMeasurement, contentOffset} = e.nativeEvent;
const distanceFromBottom = contentSize.height - layoutMeasurement.height - contentOffset.y;
if (distanceFromBottom < 72) {
console.log('바닥이 가까워요.');
} else {
console.log('바닥과 멀어졌어요.');
}
};
onScroll를 사용할때 안드로이드에서는 스크롤 없이 모든 항목을 보여줄 수 있는 상황에서는 아예 스크롤이 방지되어 상관없지만, iOS에서는 스크롤이 필요 없는 상황에서도 화면을 세로 방향으로 스와이프하면 FlatList 내부의 내용이 움직이면서 onScroll 함수가 호출된다.
따라서 contentSize.height > layoutMeasurement.height 조건을 만족할 때만 버튼을 숨기도록 로직을 수정해야 한다.
const onScroll = (e) => {
const {contentSize, layoutMeasurement, contentOffset} = e.nativeEvent;
const distanceFromBottom = contentSize.height - layoutMeasurement.height - contentOffset.y;
if (
contentSize.height - layoutMeasurement.height > 0 &&
distanceFromBottom < 72
) {
console.log('바닥이 가까워요.');
} else {
console.log('바닥과 멀어졌어요.');
}
};
onScroll Props는 ScrollView의 onScroll과 동일하다. onScroll의 자세한 내용은 아래 링크에서 확인할 수 있다.
'React Native' 카테고리의 다른 글
React Native에서 알림창(Alert) 사용하기 (0) | 2022.02.07 |
---|---|
백터 아이콘(Vector Icons) 사용하기 (0) | 2022.02.06 |
불변성을 지키면서 객체와 배열 업데이트하기 (0) | 2022.02.06 |
TextInput에 키보드 Enter 이벤트 설정하기 (0) | 2022.02.06 |
컴포넌트 터치 시 효과 주기 (0) | 2022.02.06 |