rnc 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import React, { Component } from 'react';
import { View, Text } from 'react-native';
 
export default class componentName extends Component {
  constructor(props) {
    super(props);
    this.state = {
    };
  }
 
  render() {
    return (
      <View>
        <Text> textInComponent </Text>
      </View>
    );
  }
}
 
cs


imrc


import React, { Component } from 'react';



rnss


1
2
3
const styles = StyleSheet.create({
    
});

cs



cdm

1
2
3
componentDidMount() {
        
}
cs



작업하면서 계속 추가해야겠다.

블로그 이미지

클라인STR

,

ActivityIndicator

로딩바를 표시하는 컴포넌트이다. 



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
import React, {Component} from 'react';
import {StyleSheet, View, ActivityIndicator} from 'react-native';
 
 
export default class App extends Component {
  render() {
    return (
      <View style={[styles.container, styles.horizontal]}>
        <ActivityIndicator animating="true" size="large" color="#0000ff" />
        <ActivityIndicator size="small" color="#00ff00" />
        <ActivityIndicator size="large" color="#0000ff" />
        <ActivityIndicator size="small" color="#00ff00" />
      </View>
    );
  }
}
 
const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center'
  },
  horizontal: {
    flexDirection: 'row',
    justifyContent: 'space-around',
    padding: 10
  }
})
 
cs

[App.js]



주요속성는 다음과 같다. 


animating : ActivityIndicator 표시할지 말지 여부를 나타낸다. (기본값 true)



color : spinner에 전경색을 표시한다. (기본값 회색)


size :  ActivityIndicator에 크기를 지정한다. 숫자값을 지원하는건 Android에서만 가능




원문 : https://facebook.github.io/react-native/docs/activityindicator

블로그 이미지

클라인STR

,

2018년에 당신이 알아야할 리액트 네이티브 컴포넌트 라이브러리 11가지


블로그 이미지

클라인STR

,
FlatList 컴포넌트는 데이터 구조가 비슷한 경우사용하기 위해 디자인되었다.

1
2
3
<FlatList
    data={this.state.data}
    renderItem={this._renderItem} />
cs


이 컴포넌트는 props로 data와 renderItem을 반드시 지정해야한다.

data는 FlatList에서 렌더링할 데이터를 의미한다. 데이터는 배열타입으로 배열데이터 항목은 고유의 key 값을 가지고 있어야한다. 

renderItem 함수는 data배열에 속한 데이터를 바탕으로 해당하는 컴포넌트를 리턴하도록 구현한다. 


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 {StyleSheet, Text, View, FlatList} from "react-native";
 
 
 
class SimpleList extends Component {
 
    constructor(props) {
        super(props);
        this.state = {
            data : [
                {key: "a"},
                {key: "b"},
                {key: "c"},
                {key: "d"},
                {key: "e"},
                {key: "f"},
                {key: "g"},
                {key: "h"},
                {key: "i"},
                {key: "j"},
                {key: "k"},
                {key: "l"},
                {key: "m"},
                {key: "n"},
                {key: "o"},
                {key: "p"},
                {key: "q"},
                {key: "r"}
            ]
        }
    }
 
    _renderItem = ({item}) => {
        return <Text style={styles.row}>
                    {item.key}
                </Text>
    };
 
    render() {
        return (
             <View style={styles.container}>
                <FlatList
                    data={this.state.data}
                    renderItem={this._renderItem}
                    />
             </View>
        );
    }
 
}
 
 
const styles = StyleSheet.create({
    
    container : {
        flex : 1,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: "#F5FCFF"
    }, row : {
        flex : 1,
        fontSize:24,
        padding: 42,
        borderWidth: 1,
        borderColor: "#DDDDDD"
    }
});
export default SimpleList;

cs

[SimpleListDemo.js]

_renderItem에는 FlatList에 표현할 row항목을 디자인하여 return 하게끔 구성한다. 

뉴욕API 목록 갱신하기 예제 (API 연동전)


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 {StyleSheet, Image, FlatList, View, Text } from 'react-native';
import BookItem from "./BookItem";
 
const mockBooks = [
    {
        rank : 1,
        title : "GATHERING PREY",
        author : "John Sandford",
        book_image : "https://i.postimg.cc/cLdPyZLY/host1.jpg"
    },
    {
        rank : 2,
        title : "MEMORY MAN",
        author : "David Baldacci",
        book_image : "https://i.postimg.cc/3rcwxSvd/host2.jpg"
    }
 
];
 
class BookList extends Component {
  constructor(props) {
    super(props);
    this.state = {
        data: this._addKeysToBooks(mockBooks)};
    };
 
    _renderItem = ({item}) => {
 
        return (
            <BookItem
            coverURL={item.book_image}
            title={item.key}
            author={item.author}
            />
        )
    };
 
    _addKeysToBooks = books => {
        //뉴욕타임스 api 응답을 가져와서 렌더링을 위한 key 속성을 객체에 추가 
        return books.map(book => {
          return Object.assign(book, {key: book.title});
        });
    };
    render() {
      return <FlatList
                data={this.state.data}
                renderItem={this._renderItem}
            />
    }
  }
 
  const styles = StyleSheet.create({
        container : {
            flex : 1,
            paddingTop: 22,
        }
  });
 export default BookList;

cs

[BookList.js]



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
import React, { Component } from "react";
 
import { StyleSheet, Text, View, Image, ListView } from "react-native";
 
const styles = StyleSheet.create({
  bookItem: {
    flexDirection: "row",
    backgroundColor: "#FFFFFF",
    borderBottomColor: "#AAAAAA",
    borderBottomWidth: 2,
    padding: 5,
    height: 175
  },
  cover: {
    //width: "10%", height: "20%" 
       flex: 1
       height: 150
       resizeMode: "contain" 
    },
  info: {
    flex: 3,
    alignItems: "flex-end",
    flexDirection: "column",
    alignSelf: "center",
    padding: 20
  },
  author: { fontSize: 18 },
  title: { fontSize: 18, fontWeight: "bold" }
});
 
class BookItem extends Component {
  render() {
    return (
      <View style={styles.bookItem}>
        <Image style={styles.cover} source={{uri: this.props.coverURL}} />
        <View style={styles.info}>
          <Text style={styles.author}>{this.props.author}</Text>
          <Text style={styles.title}>{this.props.title}</Text>
        </View>
 
        
      </View>
    );
  }
}
 
export default BookItem;
 
cs

[BookItem.js]


1
2
3
4
5
6
7
8
9
10
import React, {Component} from 'react';
import BookList from './bookstore/BookList';
 
export default class App extends Component {
  render() {
    return (
        <BookList/>
      );
  }
}

cs

[App.js]


실제 데이터 연결예제

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const API_KEY = "73b19491b83909c7e07016f4bb4644f9:2:60667290";
const LIST_NAME = "hardcover-fiction";
const API_STEM = "https://api.nytimes.com/svc/books/v3/lists";
 
 
function fetchBooks(list_name = LIST_NAME) {
    let url = `${API_STEM}/${LIST_NAME}?response-format=json&api-key=${API_KEY}`;
    return fetch(url)
        .then(response => response.json())
        .then(data => {
            return data.results.books;
        })
        .catch(error => {
            console.log(error);
        });
}
export default { fetchBooks: fetchBooks};
 
 
cs

[NYT.js]



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
import React, { Component } from 'react';
import {StyleSheet, Image, FlatList, View, Text } from 'react-native';
import BookItem from "./BookItem";
import NYT from "./NYT";
 
class BookList extends Component {
  constructor(props) {
    super(props);
    this.state = {
        data: []};
    };
 
 
    componentDidMount() {
        this._refreshData();
    }
 
    _renderItem = ({item}) => {
 
        return (
            <BookItem
            coverURL={item.book_image}
            title={item.key}
            author={item.author}
            />
        )
    };
 
    _addKeysToBooks = books => {
        //뉴욕타임스 api 응답을 가져와서 렌더링을 위한 key 속성을 객체에 추가 
        return books.map(book => {
          return Object.assign(book, {key: book.title});
        });
    };
 
    _refreshData = () => {
        NYT.fetchBooks().then(books => {
            this.setState({data:this._addKeysToBooks(books)});
        });
    }
 
    render() {
      return <FlatList
                data={this.state.data}
                renderItem={this._renderItem}
            />
    }
  }
 
  
 
  export default BookList;
cs

[BookList.js]

NYT 모듈을 import에 추가한다. _refreshData() 메서드를 추가하고 NYT.fetchBooks 메서드를 이용하여 데이터를 가져오게끔 코드를 추가한다. 37~39라인 




FlastList관련참고

예제소스 참고 : 빠른 모바일 앱 개발을 위한 React Native 2/E


블로그 이미지

클라인STR

,

NativeBase


NativeBase는 React Native용 UI 컴포넌트 라이브러리이다. 



1
npm install native-base --save

cs

해당 명령어로 라이브러리를 설치한다.



1
react-native link

cs

link 명령어로 라이브러리와 프로젝트를 연결한다. 


설치가 잘되면 다음과같은 메세지가 나온다.




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
import React, { Component } from 'react';
import { Container, Header, Title, Content, Footer, FooterTab, Button, Left, Right, Body, Icon, Text } from 'native-base';
export default class AnatomyExample extends Component {
  render() {
    return (
      <Container>
        <Header>
          <Left>
            <Button transparent>
              <Icon name='menu' />
            </Button>
          </Left>
          <Body>
            <Title>Header</Title>
          </Body>
          <Right />
        </Header>
        <Content>
          <Text>
            This is Content Section
          </Text>
        </Content>
        <Footer>
          <FooterTab>
            <Button full>
              <Text>Footer</Text>
            </Button>
          </FooterTab>
        </Footer>
      </Container>
    );
  }
}
cs

[NativeBase1.js]


doc사이트에 있는 간단한 예제를 실행해 보자 .


1
2
3
import NativeBase1 from './NativeBase1';
 
export default NativeBase1;
cs

[App.js]


App.js를 주석처리하고 위와 같이 코드를 변경하고 프로젝트를 실행한다.


NativeBase 컴포넌트를 이용하여 헤더, 컨텐트, 푸터를 간단하게 생성할 수 있다.


원문참조 : NativeBase


블로그 이미지

클라인STR

,

fetch API

fetch API는 Ajax를 비동기형태로 쉽게 사용할 수 있는 api 함수이다. 

1
2
3
4
5
6
7
8
9
10
11
12
fetch('http://example.com/movies.json')
  .then(function(response) {
    return response.json();
  })
  .then(function(myJson) {
    console.log(JSON.stringify(myJson));
})
.catch(function(err) {
console.log(err);
});


cs

URL을 인자로 받고 응답을 처리하기위한 Promise인 response 객체가 반환된다. 


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
import React, {Component} from 'react';
import {Platform, StyleSheet, Text, View, ActivityIndicator} from 'react-native';
 
export default class App extends Component {
 
  constructor(props) {
    super(props);
    this.state = {
      isLoading: true,
      dataSource: null
    }
  }
 
  componentDidMount() {
    return fetch('https://facebook.github.io/react-native/movies.json')
            .then ( (response) => response.json() )
            .then( (responseJson) => {
                this.setState({
                    isLoading: false,
                    dataSource: responseJson.movies,
                })
            })
        .catch((error) => {
            console.log(error)
        });
  }
 
  render() {
      if (this.state.isLoading) {
        return (
            <View style={styles.container}>
                <ActivityIndicator />
            </View>
        )
    } else {
        let movies = this.state.dataSource.map((val, key) => {
            return <View key={key} style={styles.item}><Text>{val.title}</Text></View>
        });
        return (
            <View style={styles.container}>
                
                {movies}
            </View>
        );
    }
  }
}
 
const styles = StyleSheet.create({
  container: {
      flex: 1,
      backgroundColor: '#fff',
      alignItems: 'center',
      justifyContent: 'center',
  },
  item: {
      flex: 1,
      alignSelf: 'stretch',
      margin: 10,
      alignItems: 'center',
      justifyContent: 'center',
      borderBottomWidth: 1,
      borderBottomColor: '#eee'
  }
});
 
cs

[App.js]



map 함수 참고



원문 출처 : https://www.youtube.com/watch?v=hzLDsxPGctY

fetch api : https://blog.naver.com/dmswjd93/221273203218

https://medium.com/@kkak10/javascript-fetch-api-e26bfeaad9b6




블로그 이미지

클라인STR

,

1. 아래 명령어로 react-natvie-vector-icons을 설치한다.


npm install react-native-vector-icons --save



2. link 명령어로 라이브러리와 프로젝트를 연결한다. 


react-native link react-native-vector-icons





3. import 구문을 아래와 같이 추가한다.


import Icon from 'react-native-vector-icons/Ionicons';


https://ionicons.com/  접속하여, Icon 탭에서 사용할 수 있는 아이콘 종류를 확인 할 수 있다. 



아이콘을 클릭하면 다음과 같이 하단부에 확장영역이 뜨며, Style 종류에 따른  svg파일을 다운로드 받을 수 있으면 Web Component Code를 표시한다. 


실제로 RN에서사용할때 플랫폼 접두어(ios 또는 md) + "-"+ name 명을 써서 표시한다. 


메뉴 아이콘을 클릭에서 선택하면 위와 같이 Web Component Code가 표시되는데 RN에서 사용할경우 아래과 같이 코드를 불러서 사용한다. 


<Icon name="ios-menu"  size={30} color="white"/>



아래코드에서 Ionicons 아이콘을 사용한 디자인을 살펴보자 



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
 
import React, {Component} from 'react';
import {Platform, StyleSheet, Text, View, Image, TouchableOpacity} from 'react-native';
import Icon from 'react-native-vector-icons/Ionicons';
 
 
export default class App extends Component {
  render() {
    return (
      <View style={styles.container}>
        <View style={styles.header}>
          <View style={{paddingLeft:10, flex:2}}>
            <Icon name="ios-menu"  size={30} color="white"/>
          </View>
          <View style={{flex:2,justifyContent:'flex-end', flexDirection: 'row'}}>
           <Icon name="ios-notifications-outline" size={30} color="white" />
           <Icon name="ios-search" size={30} color="white" style={{paddingRight:20, paddingLeft:20}} />
          </View>
        </View>
        
      </View>
      
    );
  }
}
 
const styles = StyleSheet.create({
  container: {
    flex: 1
  },header: {
        backgroundColor: '#808080',
        alignItems: 'center',
        justifyContent:'flex-start',
        height:60,
        flexDirection: 'row',
        paddingTop: 20,
    }
});
 
cs

[App.js]






좀더 자세한 내용은 react-native-vector-icons   참조하자


블로그 이미지

클라인STR

,


React-Native-Navigation V2 을 이용하여 SlideMenu 작성해보자. v1에서는 drawer였는데, 버전이 올라가면서 sideMenu로 변경되었다.


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
import {Navigation} from 'react-native-navigation';
import Welcome from './src/Welcome';
import SignIn from './src/SignIn';
import SignUp from './src/SignUp';
import SideMenu from './src/SideMenu';

 
 
Navigation.registerComponent('SideMenu', ()=>SideMenu );
Navigation.registerComponent('Welcome', ()=>Welcome );
Navigation.registerComponent('SignIn', ()=>SignIn );
Navigation.registerComponent('SignUp', ()=>SignUp );
 
Navigation.events().registerAppLaunchedListener( () => {
   
  Navigation.setRoot({
    root: {
      sideMenu: {
        left: {
          component: {
            id: "Drawer",
            name"SideMenu",
            passProps: {
              text'This is a left side menu screen'
            },
            
          }
        },
        center: {
          stack : {
            id:'AppStack',
            children : [
                {
                    component : {
                        name'Welcome'
                    },
                }
            ]
          }
        }
      }
    }
  });
 
  
});
 
 
 
cs

[index.js]

Navigation.setRoot root 속성 안으로 sideMenu :{... } 추가한다. 이때 center : {stack: {} ... } 속석을 반드시 지정한다. sideMenu를 설정하면 터치를 오른쪽으로해서 화면을 밀면 자동으로 sideMenu가 오픈된다. 


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
import React, {Component} from "react";
import {
    View,
    Text,
    StyleSheet,
    Button
} from "react-native";
import {Navigation} from "react-native-navigation";
 
class SideMenu extends Component {   
 
    render() {
 
        return (
            <View style={styles.container}>
                <Text>SideMenu</Text>
            </View>
        );
    }
}
 
 
export default SideMenu;
 
 
const styles = StyleSheet.create({
    
    container : {
        flex : 1,
        alignItems: 'center',
        justifyContent : 'center'
    }
});

cs

[SideMenu.js]


SideMenu 컴포넌트는 간단하게 작성한다.



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
import React, { Component } from "react";
import { View, Text, StyleSheet, Button } from "react-native";
import { Navigation } from "react-native-navigation";
 
 
class WelcomScreen extends Component {
 
 
    static get options() {
        return {
            topBar: {
                visibletrue,
                translucent: true,
                background: {
                    color: "rgba(217, 73, 114, 0.5)",
                    
                },
                leftButtons: {
                    id: 'menuButton',
                    icon: require('../image/icons-menu-25.png')
                }                    
                
            }
        };
    }
 
    constructor(props) {
        super(props);
        this.state = {
            openFlag : false
        }
        Navigation.events().bindComponent(this);
        
    }
      
 
 
    navigationButtonPressed({ buttonId }) {
        
        this.state.openFlag = !this.state.openFlag;
        if (buttonId == 'menuButton') {
            Navigation.mergeOptions('Drawer', {
              sideMenu: {
                left: {
                  visible:this.state.openFlag , 
                },
              },
            });
            
        }
        
    }
 
 
    goToScreen = (screenName) => {
        Navigation.push(this.props.componentId, {
            component: {
                name: screenName
            }
        })
    }
 
    render() {
 
        return (
            <View style={styles.container}>
                <Button title='Sign In' onPress={() => this.goToScreen('SignIn')} />
                <Button title='Sign Up' onPress={() => this.goToScreen('SignUp')} />
            </View>
        );
    }
}
 
export default WelcomScreen;
 
const styles = StyleSheet.create({
 
    container: {
        flex: 1,
        alignItems: 'center',
        justifyContent: 'center'
    }
});

cs

[Welcome.js]


static get options 함수를 이용하여 topBar에 관한 설정을 추가하고, leftButton 항목에 버튼이미지및 id를 설정한다. leftButton에 대한 이벤트를 사용하기위해서 생성자함수에 Navigation.events().bindComponent(this); 추가하고

navigationButtonPressed({ buttonId }) {..} 이벤트 발생에 대한 코드를 추가한다.

leftButton선택시 sideMenu를 open 시키기위해서 sideMenu 상태를 재정의 해야된다. 이때 사용되는 메서드가 Navigation.mergeOptions 이다.






참고 URL

https://wix.github.io/react-native-navigation/#/docs/layout-types?id=sidemenu

https://wix.github.io/react-native-navigation/#/docs/topBar-buttons


관련 포스팅 보기 


react-native-navigation v2 개발환경 설정 (ios) #1


react-native-navigation v2 Root Screen #2

react-native-navigation V2 StackNavigator #3 





블로그 이미지

클라인STR

,