0%

[React Native] FlatList으로 Infinite Scroll와 Pull Down Refresh 구현하기

https://youtu.be/Jc2MX0Ew3PE
microcode님의 리액트 네이티브 강의입니다. 이분은 말 한마디 없이 코딩만 하네요.

React Native에서 제공하는 FlatList를 사용하여 무한 스크롤(Infinite Scroll)과 Pull Down Refresh 기능을 구현합니다. FlatList에 대한 자세한 내용은 공식 문서에서 확인하세요.

이번 예제를 위해서 snack를 이용하였습니다. 아래 화면처럼 브라우저에서 코딩하고 결과를 바로 확인 할 수 있습니다. 간단한 코딩 연습을 하기에 좋은 플랫폼입니다.

샘플 컴포넌트 생성하기

App.js 파일을 수정합니다. FlatListdata 속성에는 배열 데이터를 입력합니다. 그리고 renderItem 속성에는 렌더링 함수를 입력합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import React from 'react';
import
View,
Image,
Text,
FlatList, // here
} from 'react-native';

export default class App extends React.Component

state = {
data: [1, 2, 3]


_renderItem = ({item}) => (
<Text>{item}</Text>
);

render() {
return (
<FlatList
data={this.state.data}
renderItem={this._renderItem}
/>
);



아래는 결과화면입니다.


Fake Online REST API

우리는 이번 예제를 위해서 JSONPlaceholder에서 제공하는 Fake Online REST API를 사용할 것입니다. JSONPlaceholder에서는 아래와 같이 다양한 샘플 API를 제공하고 있습니다.

이중에서 /photos API를 사용해 보겠습니다. JSON 데이터 형태는 아래와 같습니다.


서버에서 데이터 가져와서 출력하기

REST API에서 데이터를 가져오는 함수를 입력합니다. 한번에 10개씩 가져옵니다.

1
2
3
4
5
6
7
8
9
10
_getData = async () => {
const url = 'https://jsonplaceholder.typicode.com/photos?_limit=10';
fetch(url)
.then(res => res.json())
.then(json =>
this.setState({
data: json
});
});


그리고 컴포넌트가 마운트되고 나서 호출되도록 합니다.

1
2
3
componentDidMount() {
this._getData();


마지막으로 _renderItem 함수를 수정합니다.

1
2
3
4
5
6
_renderItem = ({item}) => (
<View style={{borderBottomWidth:1, marginTop: 20}}>
<Image source={{ uri: item.url }} style={{ height: 200}} />
<Text>{item.title}</Text>
</View>
);

> 여기까지 작업한 전체 코드입니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
import React from 'react';
import
View,
Image,
Text,
FlatList, // here
} from 'react-native';

export default class App extends React.Component

state = {
data: [1, 2, 3]


_getData = async () => {
const url = 'https://jsonplaceholder.typicode.com/photos?_limit=10';
fetch(url)
.then(res => res.json())
.then(json => {
this.setState({
data: json
});
});


componentDidMount() {
this._getData();


_renderItem = ({item}) => (
<View style={{borderBottomWidth:1, marginTop: 20}}>
<Image source={{ uri: item.url }} style={{ height: 200}} />
<Text>{item.title}</Text>
</View>
);

render() {
return (
<FlatList
data={this.state.data}
renderItem={this._renderItem}
keyExtractor={(item, index) => item.id}
/>
);



그리고 결과 화면입니다.


무한 스크롤 구현하기

맨 아래 항목까지 스크롤되면, 다음 데이터를 자동으로 가져와서 목록에 추가하는 기능을 구현할 것입니다… 이 기능을 Infinite Scroll 또는 무한 스크롤이라고 합니다.

statepage 변수를 추가합니다.

1
2
3
4
state = {
data: [],
page: 1 // here


그리고 _getData 함수를 수정합니다. 데이터를 가져올때마다 _page 번호를 증가합니다. 이렇게 하면 다음 요청에서는 다음 페이지의 데이터를 가져올 것입니다. 그리고 가져온 데이터를 기존 data에 추가(concat)합니다.

1
2
3
4
5
6
7
8
9
10
11
_getData = () => {
const url = 'https://jsonplaceholder.typicode.com/photos?_limit=10&_page=' + this.state.page;
fetch(url)
.then(r => r.json())
.then(data => {
this.setState({
data: this.state.data.concat(data), // 기존 data에 추가.
page: this.state.page + 1
})
});


그리고 _handleLoadMore 함수를 입력합니다. 이 함수는 스크롤이 끝까지 도달했을때 호출됩니다.

1
2
3
_handleLoadMore = () =>
this._getData();


마지막으로 render 함수를 수정합니다.

1
2
3
4
5
6
7
8
9
10
11
render() {
return (
<FlatList
data={this.state.data
renderItem={this._renderItem}
keyExtractor={(item, index) => item.id}
onEndReached={this._handleLoadMore}
onEndReachedThreshold={1
/>
);


> 다음은 전체 코드입니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import React from 'react';
import
View,
Image,
Text,
FlatList, // here
} from 'react-native';

export default class App extends React.Component

state = {
data: [],
page: 1 // here


_renderItem = ({item}) => (
<View style={{borderBottomWidth:1, marginTop: 20}}>
<Image source={{ uri: item.url }} style={{ height: 200}} />
<Text>{item.title}</Text>
<Text>{item.id}</Text>
</View>
);

// _getData 함수 수정
_getData = () => {
const url = 'https://jsonplaceholder.typicode.com/photos?_limit=10&_page=' + this.state.page;
fetch(url)
.then(r => r.json())
.then(data => {
this.setState({
data: this.state.data.concat(data),
page: this.state.page + 1
})
});


componentDidMount() {
this._getData();


// here
_handleLoadMore = () => {
this._getData();


render() {
return (
<FlatList
data={this.state.data
renderItem={this._renderItem}
keyExtractor={(item, index) => item.id}
onEndReached={this._handleLoadMore}
onEndReachedThreshold={1
/>
);



다음은 결과 화면입니다. 스크롤이 끊임없이 됩니다.


Pull Down Refresh 구현하기

이제 마지막입니다.

staterefreshing 변수를 추가합니다. refreshing 는 데이터를 가져오는 중인지를 판단합니다.

1
2
3
4
5
state = {
data: [],
page: 1,
refreshing: false // here


_handleRefresh 함수를 입력합니다. 이 함수는 화면을 Pull Down하면 호출될 것입니다. 데이터를 새로 가져올 것이기 때문에, page 번호를 1로 초기화해 줍니다.

1
2
3
4
5
6
_handleRefresh = () =>
this.setState({
refreshing: true,
page: 1,
}, this._getData);


render 함수를 수정합니다. refreshing 속성과 onRefresh 속성을 추가하였습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
render() {
return (
<FlatList
data={this.state.data
renderItem={this._renderItem}
keyExtractor={(item, index) => item.id}
onEndReached={this._handleLoadMore}
onEndReachedThreshold={1
refreshing={this.state.refreshing}
onRefresh={this._handleRefresh}
/>
);


마지막으로 _getData 함수를 수정합니다. refreshingtrue 일때는 가져온 데이터를 기존 데이터에 추가(concat)하지 않습니다.

1
2
3
4
5
6
7
8
9
10
11
12
_getData = () => {
const url = 'https://jsonplaceholder.typicode.com/photos?_limit=10&_page=' + this.state.page;
fetch(url)
.then(r => r.json())
.then(data => {
this.setState({
data: this.state.refreshing?data:this.state.data.concat(data),
page: this.state.page + 1,
refreshing: false
})
});


다음은 결과 화면입니다. 화면을 아래로 당기면 onRefresh 이벤트가 발생합니다. 새로고침 해도 같은 데이터를 가져오기 때문에 화면의 변화는 없네요.


예제에 사용한 코드는 여기에서 확인할 수 있습니다.

감사합니다.


Sponsored ( Powered by dclick )
DCLICK: 광고 기능을 소개 합니다

지난주에 dclick 에서 Advertise 기능이 오픈 되었습니다. Advertise 메뉴 …


Originally posted on http://steemit.com