본문 바로가기
안드로이드 웹앱 콘테츠 개발자 양성(국비지원)/HybridApp

HybridApp-React Native 2세대 (기능 - DataArchitecture- Context API, 전역변수 같은)

by 차누감 2020. 1. 30.

MVC나 MVP를 사용하지 않고 flux 패턴을 사용하여, Context API를 이용한다. ( 전역변수 사용 하는 것 같은 효과 )

<최종 화면>

1. Main.js 파일 내에서 전역변수처럼 사용해서 다른 클래스에서 사용할 수 있다.

2. Second2.js 파일을 새로 만들어서 보라색 Text와 녹색 버튼을 만들었다. 

   다른 파일에서 import 해서 Main.js의 전역 변수 같은 변수를 사용한다.


실행 전에 AVD를 켜놓자.

작업할 경로까지 접근하여 init하자.

만든 폴더로 가서 run하자.

RN22DataArchitectureContextAPI폴더에 Main.js 파일을 만들자.

우선 값을 전달하지 않지만, Main, First, Second class를 만들자.

Main class 위에 전역 변수를 선언하듯, context 객체를 만들자.

그리고 변수 선언은 <.Provider>태그 안에 만들어야 한다.

이제 First class에서 Main class에 Provider 태그 안에 저장되어 있는 value안에 data를 사용해보자. 

똑같이 Second class에서도  Main class에 Provider 태그 안에 저장되어 있는 value안에 data를 사용해보자. 

value의 data는 state의 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
72
73
74
75
76
import React, {Component} from 'react';
import {View, Text, Button} from 'react-native';
 
// Flux패턴(일종의 전역변수사용 패턴)을 구현한 Context API사용
//Context객체 만들기 (React클래스의 메소드)
const MyContext= React.createContext();
 
export default class Main extends Component{
    // Main의 state데이터
    state={data:"Hello"};
 
    render(){
        return ( 
            // 자식들에게 데이터를 전달하지 않고 값을 제공하는
            // 제공자 컴포넌트(Provider) 사용
            // Provider컴포넌트의 자식들은 어느 계층에서든
            // Consumer(소비자)로서 Provider의 value 속성값을 사용할 수 있음.
            <MyContext.Provider
                value={
                    //여기가 일종의 전역변수 만드는 영역
                    {
                        data:this.state.data, //데이터
                    }
                }>
                
                <View style={{padding:16}}>
                    <Text>Main의 데이터 : {this.state.data}</Text>
 
                    {/* 자식컴포넌트 - 데이터 전달 */}
                    <First></First>
                </View>
            </MyContext.Provider>);
    }
}//Main
 
class First extends Component{
    render(){
        return(
            <View style={{marginTop:16, backgroundColor:'lightgreen', padding:16}}>
                <Text>First : </Text>
                {/* Main의 Provider에 의해 저장된 value를 사용하고 싶다면 */}
                {/* Consumer(소비자) 컴포넌트 사용 */}
                <MyContext.Consumer>
                    {/* 이 컨슈머 컴포넌트가 보여줄 뷰를 return하는 콜백화살표 함수 작성 */}
                    {
                        // 컨슈머가 자동으로 호출해주는 함수
                        (value)=>//파라미터: Provider의 value속성 값
                            return <Text>Main의 전역 데이터 : {value.data}</Text>
                        }
                    }
                </MyContext.Consumer>
 
                {/* 손자컴포넌트 - 데이터 전달 없음 */}
                <Second></Second>
            </View>
        );
    }
}
 
class Second extends Component{
    render(){
        return(
            <View style={{marginTop:16, backgroundColor:'blue', padding:16,}}>
                <Text style={{color:'white'}}>Second : </Text>
                {/* Main의 전역 value사용하기 */}
                <MyContext.Consumer>
                    {
                        (value)=>{
                            return <Text style={{color:'yellow'}}>Main의 전역 데이터 : {value.data}</Text>
                        }
                    }
                </MyContext.Consumer>
            </View>
        );
    }
}
 

<실행 화면> 데이터 전달을 안해도 사용할 수 있다.

text 값을 변경하기 위해 메소드를 전달하자. 

이 메소드도 전역변수처럼 Provider에 넣고 사용하자.

Second class에서 버튼을 눌렀을 때, Provider에 있는 메소드를 호출한다. (파라미터로 'Nice'문자열을 준다.)

Provider에 value.changeData는 Main class의 changeData를 가리키고 있다.

결론, Main의 changeData()를 호출한 것이다.

<실행 화면> Mian의 전역 데이터를 바꿔주면, 전체 해당 text가 변경된다. 

RN22DataArchitectureContextAPI폴더에 새로 Second2.js 파일을 만들자.

다시 Main.js 파일로 와서 새로 만든 Second2를 사용해보자.

우선 Second2를 알아들으려면 import를 해야한다.

그리고 Second2에 데이터를 전달하려면 Main의 Context객체를 알아들으려면 export를 해줘야 한다.

Second2.js 파일로 와서 import로 Main.js에 있는 Context 객체를 인식한다.

MyContext.Provider 안에는 value.dara, value.changeData가 있다. 둘다 사용해보자.


<복붙용 코드>

Main.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
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
import React, {Component} from 'react';
import {View, Text, Button} from 'react-native';
import Second2 from './Second2';
 
// Flux패턴(일종의 전역변수사용 패턴)을 구현한 Context API사용
//Context객체 만들기 (React클래스의 메소드)
export const MyContext= React.createContext(); //하나의 문서에서는 export default 한번만 가능.나머지는 export
//만약 class가 없어서 export default를 안썻다면 const에는 작성하면서 export default 못씀
export default class Main extends Component{
    // Main의 state데이터
    state={data:"Hello"};
 
    changeData=(data)=>{
        //this.setState({data:data}); //키값과 변수명이 같으면 변수명만 작성할 수 있음
        this.setState({data});
    }
 
    render(){
        return ( 
            // 자식들에게 데이터를 전달하지 않고 값을 제공하는
            // 제공자 컴포넌트(Provider) 사용
            // Provider컴포넌트의 자식들은 어느 계층에서든
            // Consumer(소비자)로서 Provider의 value 속성값을 사용할 수 있음.
            <MyContext.Provider
                value={
                    //여기가 일종의 전역변수 만드는 영역
                    {
                        data:this.state.data, //데이터
                        changeData: this.changeData //메소드
                    }
                }>
                
                <View style={{padding:16}}>
                    <Text>Main의 데이터 : {this.state.data}</Text>
 
                    {/* 자식컴포넌트 - 데이터 전달 */}
                    <First></First>
                </View>
            </MyContext.Provider>);
    }
}//Main
 
class First extends Component{
    render(){
        return(
            <View style={{marginTop:16, backgroundColor:'lightgreen', padding:16}}>
                <Text>First : </Text>
                {/* Main의 Provider에 의해 저장된 value를 사용하고 싶다면 */}
                {/* Consumer(소비자) 컴포넌트 사용 */}
                <MyContext.Consumer>
                    {/* 이 컨슈머 컴포넌트가 보여줄 뷰를 return하는 콜백화살표 함수 작성 */}
                    {
                        // 컨슈머가 자동으로 호출해주는 함수
                        (value)=>//파라미터: Provider의 value속성 값
                            return <Text>Main의 전역 데이터 : {value.data}</Text>
                        }
                    }
                </MyContext.Consumer>
 
                {/* 손자컴포넌트 - 데이터 전달 없음 */}
                <Second></Second>
 
                {/* 별도의 js문서의 컴포넌트 사용 - 데이터 전달X */}
                <Second2></Second2>
            </View>
        );
    }
}
 
class Second extends Component{
    render(){
        return(
            <View style={{marginTop:16, backgroundColor:'blue', padding:16,}}>
                <Text style={{color:'white'}}>Second : </Text>
                {/* Main의 전역 value사용하기 */}
                <MyContext.Consumer>
                    {
                        (value)=>{
                            return (
                                <View>
                                    <Text style={{color:'yellow'}}>Main의 전역 데이터 : {value.data}</Text>
                                    <Button title="change data" color="orange" onPress={()=>{value.changeData('Nice')}}></Button>
                                </View>
                            );
                        }
                    }
                </MyContext.Consumer>
            </View>
        );
    }
}
 

Second2.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
import React, {Component} from 'react';
import {View, Text, Button} from 'react-native';
 
import {MyContext} from './Main'//export로 받아와서 중괄호 써야됨. export default면 중괄호 없음.
 
export default class Second2 extends Component{
    render(){
        return(
            <View>
                <MyContext.Consumer>
                    {
                        (value)=>//return ;생략..
                            <View style={{marginTop:16, backgroundColor:'indigo'}}>
                                <Text style={{color:'white'}}>Main의 전역데이터 : {value.data}</Text>
                                <Button title="button" color="green" onPress={()=>{value.changeData('Good')}}></Button>
                            </View>
                            )  
                    }
                </MyContext.Consumer>
            </View>
        );
    }
    
}
 

댓글