props properties를 줄인 표현으로 컴포넌트 속성을 설정할 때 사용하는 요소이다. props 값은 해당 컴포넌트를 불러와 사용하는 부모 컴포넌트에서만 설정할 수 있다. 


[props 값 설정 및 검증]



props 검증 : propTypes은 컴포넌트의 필수 props를 지정하거나 props 타입을 지정할  때 사용한다.

1
2
import PropTypes from 'prop-types';
 
cs


1
2
3
4
static propTypes = {
    navigator : PropTypes.object,
    componentId : PropTypes.string
  }

cs


필수 propTypes 설정

1
2
3
4
5
6
static propTypes = {
 
 name : PropTypes.string,
 age : PropTypes.number.isRequired
 
}

cs


발췌 : 리액트를 다루는 기술 

블로그 이미지

클라인STR

,
React Native 프로젝트 생성후 React Native Navigation V2 환경설정을 한다.

npm i react-native-ui-lib 명령어로 해당 라이브러리 설치한다.



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
import {Navigation} from 'react-native-navigation';
import PostList from './src/PostList';
import AddPost from './src/AddPost';
 
 
Navigation.registerComponent('blog.PostList', ()=>PostList );
Navigation.registerComponent('blog.AddPost', ()=>AddPost );
 
Navigation.events().registerAppLaunchedListener(() => {
    Navigation.setRoot({
      root: {
        stack: {
          children: [
            {
              component: {
                name'blog.PostList',
                options: {
                  topBar: {
                    title: {
                      text'Blog'
                    }
                  }
                }
              }
            }
          ],
        }
      }
    });
  });
  
cs

[index.js]

PostList 화면과 AddPost 화면을 두개를 먼저 작성해보자.

Navigation.registerComponent, Navigatio.setRoot 메서드를 이용하여 화면을 등록하고 root 화면은 PostList 컴포넌트를 등록한다. 

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
58
59
60
import React, { Component } from 'react';
import {View, Text} from 'react-native-ui-lib';
import PropTypes from 'prop-types';
import { Navigation } from 'react-native-navigation';
 
class PostList extends Component {
 
  static propTypes = {
    navigator : PropTypes.object,
    componentId : PropTypes.string
  }
 
  static get options() {
    return {
      topBar: {
        rightButtons: [
          {
            id: 'addPost',
            text'Add'
          }
        ]
      }
    };
  }
 
  constructor(props) {
    super(props);
    Navigation.events().bindComponent(this);
  }
 
 
  navigationButtonPressed({buttonId}) {
    if (buttonId === 'addPost') {
      this.showAddPostModal();
    }
  }
 
  showAddPostModal() {
    Navigation.showModal({
      stack: {
        children: [{
          component: {
            name'blog.AddPost',
          }
        }]
      }
    });
  }  
 
  render() {
      return (
        <View flex center bg-blue60>
          <Text onPress={this.pushViewPostScreen}>Posts List Screen</Text>
        </View>
      );
    }
    
}
 
export default PostList;
cs

[PostList.js]

get options 메서드를 이용하여 Navigator 에 동작과 모양을 설정할 수 있고, index.js 또는 레이아웃을 호출하는 로직에서 레이아웃 계층을 이용하여 Navigator 동작이나 레이아웃을 정의할 수도 있다.

top Bar 속성을을 이용하여 right버튼에 Add 텍스트를 설정하고, Navigation 이벤트 객체를 선언한뒤에 rightButton 터치할경우 Navigation.showModal 이용하여 AddPost 화면을 호출한다.

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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
import React, { Component } from 'react';
import {View, Text, TextField} from 'react-native-ui-lib';
import {Navigation} from 'react-native-navigation';
import PropTypes from 'prop-types';
 
 class AddPost extends Component {
 
    static propTypes = {
        componentId:PropTypes.string
    }
 
    static get options() {
        return {
          topBar: {
            title: {
              text'Add Post'
            },
            rightButtons: [{
              id: 'saveBtn',
              text'Save',
              enabled: false
            }],
            leftButtons: [{
              id: 'cancelBtn',
              text'Cancel'
            }]
          }
        };
      }
 
    constructor(props) {
        super(props);
        Navigation.events().bindComponent(this);
        this.onChangeText = this.onChangeText.bind(this);
    }
 
    navigationButtonPressed({buttonId}) {
        if (buttonId === 'cancelBtn') {
          Navigation.dismissModal(this.props.componentId);
        } else if (buttonId === 'saveBtn') {
          alert('saveBtn');
        }
      }
    
      onChangeText(text) {
        Navigation.mergeOptions(this.props.componentId, {
          topBar: {
            rightButtons: [{
              id: 'saveBtn',
              text'Save',
              enabled: !!text
            }]
          }
        });
      }
    
 
      render() {
        return (
          <View flex center bg-green60>
            <TextField
              placeholder="Start writing to enable the save btn"
              onChangeText={this.onChangeText}
              hideUnderline
            />
          </View>
        );
      }
    
}
 
export default AddPost;
 
cs

[AddPost.js]

Add Post화면에서 left, right 버튼을 생성하고 (12~29) navigationButtonPressed 메서드를 이용하여 해당버튼을 이벤트를 개치하여 로직을 처리한다. 이때 button에 id속성으로 버튼 눌러졌는지를 구별한다. Navigation.dismissModal(this.props.componentId) 이용하여 호출된 모달 화면을 종료시킨다. 


https://wix.github.io/react-native-navigation/#/docs/screen-api?id=showmodallayout-

원문출처  링크클릭

블로그 이미지

클라인STR

,


이전포스팅 예제에서 소스코드를 변경하여 실습하였다.

이전포스팅  클릭


react-native-xml2js 라이브러리를 설치합니다.


1
npm install react-native-xml2js
cs



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
const API_KEY = "xSpkBj5Uf8pu8S.......";
const API_STEM = "http://openapi.airkorea.or.kr/openapi/services/rest/ArpltnInforInqireSvc/getCtprvnRltmMesureDnsty";
var parseString = require('react-native-xml2js').parseString;
 
var SIDO = "경남";
function fetchData() {
    SIDO = encodeURIComponent(SIDO);
    var url = `${API_STEM}?serviceKey=${API_KEY}&numOfRows=10&pageNo=1&sidoName=${SIDO}&ver=1.3`;
   
    return fetch(url)
        .then(response => response.text())
        .then(data => {
            console.log(data);
            parseString(data, function (err, result) {
                console.dir(result);
                console.log(JSON.stringify(result))
                console.log(JSON.parse(JSON.stringify(result)));
                
            });
        })
        .catch(error => {
            console.log(error);
        });
}
export default { fetchData: fetchData};
 
cs


1
2
3
parseString(xml, function (err, result) {
    console.dir(result);
});

cs

위와 같이 해당구문을 이용하여 XML 응답값을 쉽게 파싱할 수 있다. 

JSON.stringfy  이용하여 JSON String 값으로 변경하고, 이를 JSON.parse 이용하여 Json Object 형태로 만들어 줍니다. 



https://beautifier.io/ 이용하여 JSON으로 변경된 데이터를 이쁘게 다시 펼쳐보면 ...


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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
{
    "response": {
        "header": [{
            "resultCode": ["00"],
            "resultMsg": ["NORMAL SERVICE."]
        }],
        "body": [{
            "items": [{
                "item": [{
                    "stationName": ["회원동"],
                    "mangName": ["도시대기"],
                    "dataTime": ["2019-01-07 23:00"],
                    "so2Value": ["0.004"],
                    "coValue": ["0.7"],
                    "o3Value": ["0.022"],
                    "no2Value": ["0.022"],
                    "pm10Value": ["71"],
                    "pm10Value24": ["60"],
                    "pm25Value": ["43"],
                    "pm25Value24": ["31"],
                    "khaiValue": ["90"],
                    "khaiGrade": ["2"],
                    "so2Grade": ["1"],
                    "coGrade": ["1"],
                    "o3Grade": ["1"],
                    "no2Grade": ["1"],
                    "pm10Grade": ["2"],
                    "pm25Grade": ["2"],
                    "pm10Grade1h": ["2"],
                    "pm25Grade1h": ["3"]
                }, {
                    "stationName": ["봉암동"],
                    "mangName": ["도시대기"],
                    "dataTime": ["2019-01-07 23:00"],
                    "so2Value": ["0.003"],
                    "coValue": ["0.6"],
                    "o3Value": ["0.015"],
                    "no2Value": ["0.024"],
                    "pm10Value": ["45"],
                    "pm10Value24": ["43"],
                    "pm25Value": ["31"],
                    "pm25Value24": ["25"],
                    "khaiValue": ["74"],
                    "khaiGrade": ["2"],
                    "so2Grade": ["1"],
                    "coGrade": ["1"],
                    "o3Grade": ["1"],
                    "no2Grade": ["1"],
                    "pm10Grade": ["2"],
                    "pm25Grade": ["2"],
                    "pm10Grade1h": ["2"],
                    "pm25Grade1h": ["2"]
                }, {
                    "stationName": ["상봉동"],
                    "mangName": ["도시대기"],
                    "dataTime": ["2019-01-07 23:00"],
                    "so2Value": ["0.003"],
                    "coValue": ["0.6"],
                    "o3Value": ["0.014"],
                    "no2Value": ["0.034"],
                    "pm10Value": ["58"],
                    "pm10Value24": ["54"],
                    "pm25Value": ["35"],
                    "pm25Value24": ["28"],
                    "khaiValue": ["82"],
                    "khaiGrade": ["2"],
                    "so2Grade": ["1"],
                    "coGrade": ["1"],
                    "o3Grade": ["1"],
                    "no2Grade": ["2"],
                    "pm10Grade": ["2"],
                    "pm25Grade": ["2"],
                    "pm10Grade1h": ["2"],
                    "pm25Grade1h": ["2"]
                }, {
                    "stationName": ["대안동"],
                    "mangName": ["도시대기"],
                    "dataTime": ["2019-01-07 23:00"],
                    "so2Value": ["0.004"],
                    "coValue": ["0.7"],
                    "o3Value": ["0.015"],
                    "no2Value": ["0.015"],
                    "pm10Value": ["58"],
                    "pm10Value24": ["51"],
                    "pm25Value": ["36"],
                    "pm25Value24": ["27"],
                    "khaiValue": ["79"],
                    "khaiGrade": ["2"],
                    "so2Grade": ["1"],
                    "coGrade": ["1"],
                    "o3Grade": ["1"],
                    "no2Grade": ["1"],
                    "pm10Grade": ["2"],
                    "pm25Grade": ["2"],
                    "pm10Grade1h": ["2"],
                    "pm25Grade1h": ["3"]
                }, {
                    "stationName": ["상대동"],
                    "mangName": ["도시대기"],
                    "dataTime": ["2019-01-07 23:00"],
                    "so2Value": ["0.007"],
                    "coValue": ["0.7"],
                    "o3Value": ["0.019"],
                    "no2Value": ["0.028"],
                    "pm10Value": ["57"],
                    "pm10Value24": ["51"],
                    "pm25Value": ["28"],
                    "pm25Value24": ["23"],
                    "khaiValue": ["71"],
                    "khaiGrade": ["2"],
                    "so2Grade": ["1"],
                    "coGrade": ["1"],
                    "o3Grade": ["1"],
                    "no2Grade": ["1"],
                    "pm10Grade": ["2"],
                    "pm25Grade": ["2"],
                    "pm10Grade1h": ["2"],
                    "pm25Grade1h": ["2"]
                }, {
                    "stationName": ["명서동"],
                    "mangName": ["도시대기"],
                    "dataTime": ["2019-01-07 23:00"],
                    "so2Value": ["0.004"],
                    "coValue": ["0.7"],
                    "o3Value": ["0.024"],
                    "no2Value": ["0.029"],
                    "pm10Value": ["57"],
                    "pm10Value24": ["55"],
                    "pm25Value": ["28"],
                    "pm25Value24": ["26"],
                    "khaiValue": ["77"],
                    "khaiGrade": ["2"],
                    "so2Grade": ["1"],
                    "coGrade": ["1"],
                    "o3Grade": ["1"],
                    "no2Grade": ["1"],
                    "pm10Grade": ["2"],
                    "pm25Grade": ["2"],
                    "pm10Grade1h": ["2"],
                    "pm25Grade1h": ["2"]
                }, {
                    "stationName": ["웅남동"],
                    "mangName": ["도시대기"],
                    "dataTime": ["2019-01-07 23:00"],
                    "so2Value": ["0.005"],
                    "coValue": ["0.8"],
                    "o3Value": ["0.020"],
                    "no2Value": ["0.029"],
                    "pm10Value": ["63"],
                    "pm10Value24": ["64"],
                    "pm25Value": ["30"],
                    "pm25Value24": ["26"],
                    "khaiValue": ["84"],
                    "khaiGrade": ["2"],
                    "so2Grade": ["1"],
                    "coGrade": ["1"],
                    "o3Grade": ["1"],
                    "no2Grade": ["1"],
                    "pm10Grade": ["2"],
                    "pm25Grade": ["2"],
                    "pm10Grade1h": ["2"],
                    "pm25Grade1h": ["2"]
                }, {
                    "stationName": ["가음정동"],
                    "mangName": ["도시대기"],
                    "dataTime": ["2019-01-07 23:00"],
                    "so2Value": ["0.006"],
                    "coValue": ["-"],
                    "o3Value": ["-"],
                    "no2Value": ["-"],
                    "pm10Value": ["-"],
                    "pm10Value24": ["-"],
                    "pm25Value": ["-"],
                    "pm25Value24": ["-"],
                    "khaiValue": ["-"],
                    "khaiGrade": [""],
                    "so2Grade": [""],
                    "coGrade": [""],
                    "o3Grade": [""],
                    "no2Grade": [""],
                    "pm10Grade": [""],
                    "pm25Grade": [""],
                    "pm10Grade1h": [""],
                    "pm25Grade1h": [""]
                }, {
                    "stationName": ["용지동"],
                    "mangName": ["도시대기"],
                    "dataTime": ["2019-01-07 23:00"],
                    "so2Value": ["0.003"],
                    "coValue": ["0.3"],
                    "o3Value": ["0.030"],
                    "no2Value": ["0.020"],
                    "pm10Value": ["48"],
                    "pm10Value24": ["48"],
                    "pm25Value": ["25"],
                    "pm25Value24": ["24"],
                    "khaiValue": ["72"],
                    "khaiGrade": ["2"],
                    "so2Grade": ["1"],
                    "coGrade": ["1"],
                    "o3Grade": ["1"],
                    "no2Grade": ["1"],
                    "pm10Grade": ["2"],
                    "pm25Grade": ["2"],
                    "pm10Grade1h": ["2"],
                    "pm25Grade1h": ["2"]
                }, {
                    "stationName": ["반송로"],
                    "mangName": ["도로변대기"],
                    "dataTime": ["2019-01-07 23:00"],
                    "so2Value": ["0.004"],
                    "coValue": ["0.6"],
                    "o3Value": ["0.018"],
                    "no2Value": ["0.018"],
                    "pm10Value": ["205"],
                    "pm10Value24": ["81"],
                    "pm25Value": ["30"],
                    "pm25Value24": ["25"],
                    "khaiValue": ["101"],
                    "khaiGrade": ["3"],
                    "so2Grade": ["1"],
                    "coGrade": ["1"],
                    "o3Grade": ["1"],
                    "no2Grade": ["1"],
                    "pm10Grade": ["3"],
                    "pm25Grade": ["2"],
                    "pm10Grade1h": ["4"],
                    "pm25Grade1h": ["2"]
                }]
            }],
            "numOfRows": ["10"],
            "pageNo": ["1"],
            "totalCount": ["30"]
        }]
    }
}

cs


해당형태로 변경된것을 알 수 있다. 


JSON.parse 참고

JSON.stringfy 참고



블로그 이미지

클라인STR

,

공공데이터 포털에서 제공하는 API를사용하여 날씨앱을 제작할려고 이것저것 알아보는중 XML 파싱에대해서 실습한 내용을 기록으로 남긴다. 


XMLDOM 라이브러리를 사용하였다. 


npm install xmldom   라이브러리를 설치한다. 


 공공데이터 포털에서 사용할 서비스는 대기오염정보 조회 서비스 이다. 해당 API를 사용하기 위해서 회원가입을 하고 서비스 신청을 선택해야된다. 


실제 테스트로 사용할 API는 시도별 실시간 측정정보 조회서비스이다. API 조회시 응답 데이터 포맷이 XML이다. 


미리보기 버튼을 선택시 해당 XML값이 리턴된다.



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
const API_KEY = "xSpkBj5Uf8pu8S%...."; //key는 ..처리함
const API_STEM = "http://openapi.airkorea.or.kr/openapi/services/rest/ArpltnInforInqireSvc/getCtprvnRltmMesureDnsty";
var DOMParser = require('xmldom').DOMParser;
var SIDO = "경남";
function fetchData() {
    SIDO = encodeURIComponent(SIDO);
    var url = `${API_STEM}?serviceKey=${API_KEY}&numOfRows=10&pageNo=1&sidoName=${SIDO}&ver=1.3`;
    
    return fetch(url)
        .then(response => response.text())
        .then(data => {
            console.log(data);
            var xmlDoc = new DOMParser().parseFromString(data, 'text/xml');
            var x=xmlDoc.getElementsByTagName("item");
            
            for (var i=0;i<x.length;i++){
                console.log(x[i].childNodes);
                var nodeList = x[i].childNodes;
 
                for (var j=0; j<nodeList.length; j++) {
                    var item = nodeList[j];
                    
                    if (item.firstChild) {
                        console.log(item.nodeName +" : "+item.childNodes[0].nodeValue);
                    }
                }
            }
        
            return xmlDoc;
        })
        .catch(error => {
            console.log(error);
        });
}
export default { fetchData: fetchData};
 
 
cs

[Data.js]

fetch함수내에 13라인에 DOMParser()를 생성한후 parseFromString 메서드를 사용하여 문자열을 XML로 파싱할 수 있게 변경한다. 

xml 구조상 <items> 하위에 <item>...</item> 앨리먼트로 존재한다. getElementsByTagName메서드로 다수의 item을 선택한후 childeNodes를 메서드를 이용하여 NodeList에 접근한다. NodeList내부에는 Element, Text 객체로 구성되어있는데, 이때 firstChild메서드를 이용하여 Elemente 내에 Node 속성에 접근하였다. XML 구조를 명확하게 보기위해서는 console.log() 함수를 이용하여 데이터 구조를 찍어보자.




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
import React, {Component} from 'react';
import {Platform, StyleSheet, Text, View} from 'react-native';
import Data from "./src/Data";
 
 
 
export default class App extends Component {
 
  
  componentDidMount() {
    Data.fetchData().then(data => {
      
    }); 
  }
 
  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.welcome}>Welcome to React Native!</Text>        
      </View>
    );
  }
}
 
const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
  instructions: {
    textAlign: 'center',
    color: '#333333',
    marginBottom: 5,
  },
});
 
cs

[App.js]

App.js에는 componentDidMound() {..} 함수내에서 fetchData()함수를 호출하는 간단한 코드이다.


공공데이터 포털에서 제공하는 API는 https요청이 아닌 http요청이므로 

아래링크를 참조하여 http요청을 허용해야 한다.


http허용설정링크 참조  <== 클릭





참고

xmldom

xmldom예제

https://developer.mozilla.org/en-US/docs/Web/API/DOMParser

https://developer.mozilla.org/ko/docs/Web/API/Node/childNodes

블로그 이미지

클라인STR

,

샘플코드 작성중 아래와 같은 오류가 나면서 프로그램이 제대로 실행되지 않는 오류가 발생하였다.


현재 모든 실습 샘플은 리액트네이티브 구버전인 0.56.0으로 테스트하고있었다. 

구글링 해서 찾아보니 아래와 같이 해결하면 정상적으로 프로젝트가 실행되었다. 


1
npm install --save-dev react-devtools-core@3.4.2
cs


해당패키지를 설치하고 에뮬레이터 및 컴파일러를 종료후 재실행한다.


2019년1월5일 현재 react-devtools-core버전이 3.4.3이 나오면서 이문제는 해결된듯 보인다. 기존에 작성된 프로젝트인경우 react-devtools-core버전을 3.4.3으로 변경한다음. npm install 명령어를 실행한후 프로젝트를 재기동 해보자.


참고 

https://github.com/facebook/react-native/issues/22865

https://github.com/facebook/react-native/issues/22863

블로그 이미지

클라인STR

,

이전글 바로가기 


react-native-elements 라이브러리를 설치한다. 


1
npm install --save react-native-elements
cs




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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
import React, { Component } from "react";
import { View, Text, FlatList, ActivityIndicator } from "react-native";
import { List, ListItem, SearchBar } from "react-native-elements";
 
class FlatListDemo extends Component {
 
    constructor(props) {
        super(props);
 
        this.state = {
            loading:false,
            data: [],
            page: 1,
            seed: 1,
            error: null,
            refreshing: false
        };
    }
 
 
    componentDidMount() {
        this.makeRemoteRequest();
    }
 
    makeRemoteRequest = () => {
        const {page, seed} = this.state;
        const url = 'https://randomuser.me/api/?seed=${seed}&page=${page}&results=20';
        this.setState({loading: true});
 
        fetch(url)
        .then(response => response.json())
        .then(response => {
            this.setState({
                data: page === 1 ? response.results : [...this.state.data, ...response.results],
                error: response.error || null,
                loading: false,
                refreshing: false
              });
        })
        .catch(error => {
            this.setState({error, loading: false});
        })
    }
 
 
 
      render() {
        return (
        <List>
            <FlatList
              data={this.state.data}
              renderItem={({ item }) => (
                <ListItem
                  title={`${item.name.first} ${item.name.last}`}
                  subtitle={item.email}
                  avatar={{ uri: item.picture.thumbnail }}
                />
              )}
              keyExtractor={item => item.email}
            />
         <List/>
        
        );
      }
    
    
}
 
 
export default FlatListDemo;
 
cs

[FlatListDemo.js]

생성자 함수에 state 값을 초기화한다. loading(로딩여부), data(dataSource), page or seed (스크롤페이징하기위해서 필요한 파라메터), refreshing (리플레쉬여부) , makeRemoteRequest 는  API로부터 데이터를 가져오기 위한 함수이다.  List, ListItem은 react-native-elements 제공하는 UI 라이브러리이다.

title은 리스트의제목, subTitle은 subtitle 또는 View 에해당하는 내용을 지정하며, avatar 속성은 React Native Image Source 사용할때 지정하는 속성이다. 

roundAvatar 속성을 지정하면 Image 가 둥글게 영역이 지정되서 보인다.

keyExtractor 속성에 경우 기본으로 지정된 key값대신에 action을 지정했을경우에 ID값을 지정할 수 있다. 


[roundAvatar 지정되지않은경우]


[roundAvatar 지정된경우]


Lists, ListItem을 사용하면, 리스트형태에 UI를 빠르고 간편하게 만들 수 있다. 


화면 최상단, 최하단에 구분선을 삭제할경우 아래와같이 추가로 코드를 수정해야한다. 



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
render() {
        return (
          <List
            containerStyle={{borderTopWidth : 0, borderBottomWidth : 0}}
          >
            <FlatList
              data={this.state.data}
              renderItem={({ item }) => (
                <ListItem
                  roundAvatar
                  title={`${item.name.first} ${item.name.last}`}
                  subtitle={item.email}
                  avatar={{ uri: item.picture.thumbnail }}
                  containerStyle={{borderBottomWidth:0}}
                />
              )}
              keyExtractor={item => item.email}
              ItemSeparatorComponent={this.renderSeparator}
            />
          </List>
        
        );
      }
cs

List, ListItem containerStyle TopWidth, BottomWidth 값을 0으로 바꾼다. 

ItemSeparatorComponent 메서드를 아래와 같이 구현한다. 


1
2
3
4
5
6
7
8
9
10
11
12
renderSeparator = () => {
        return (
          <View
            style={{
              height1,
              width"86%",
              backgroundColor: "#CED0CE",
              marginLeft: "14%"
            }}
          />
        );
      };
cs


Header와 Footer를 추가해보자 .


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
  renderHeader = () => {
        return <SearchBar placeholder="Type Here..." lightTheme round />;
      };
    
      renderFooter = () => {
        if (!this.state.loading) return null;
    
        return (
          <View
            style={{
              paddingVertical: 20,
              borderTopWidth: 1,
              borderColor: "#CED0CE"
            }}
          >
            <ActivityIndicator animating size="large" />
          </View>
        );
      };
 
cs


1
2
3
4
5
6
<FlatList
            
              ... 
              ListHeaderComponent={this.renderHeader}
              ListFooterComponent={this.renderFooter}
            />
cs


ListHeaderComponent, ListFooterComponent 속성에 함수들을 연결시킨다. 




원문링크 





블로그 이미지

클라인STR

,

함수의 나머지 매개변수를 하나로 모아 배열값으로 사용할 수 있게한다. 


1
2
3
4
function fun1(...theArgs) {
  console.log(theArgs.length);
}
 
cs





1
2
3
4
5
6
7
8
function multiply(multiplier, ...theArgs) {
  return theArgs.map(function (element) {
    return multiplier * element;
  });
}
 
var arr = multiply(2123);
console.log(arr); // [2, 4, 6]
cs


나머지매개변수 참고문서

블로그 이미지

클라인STR

,

FlastListComponent 포스팅시 Image컴포넌트에 url 리소스를 http요청으로 할 경우 이미지가 표시되지 않는 경우가 발생하였다.


구글링을 해서 검색 해보니 IOS 플랫폼에 경우 앱전송 보안변경으로 인해 http요청시 이미지가 정상적으로 표시되지 않는경우가 발생하였다. 상용서비스가 아니라 테스트 코드인경우는 https로 이미지를 올려서 해당오류를 개선하였다.


http를 허용하기위해서는 ReactNative 프로젝트를 Xcode로 Open 한다.



Project Navigator에 info.plist 파일을 선택하고, App Transport Security Settings 하위에 Allow Arbitrary Loads 속성을 추가하고 Value 값을 Yes로 변경한다. 



참고 : https://ads-developers.googleblog.com/2015/08/handling-app-transport-security-in-ios-9.html

https://github.com/facebook/react-native/issues/8520

https://github.com/facebook/react-native/issues/13293





블로그 이미지

클라인STR

,