일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- Push
- github
- Notification
- AWS
- JavaScript
- MongoDB
- graphql
- 네이티브
- 배포
- EC2
- 카카오
- NATIVE
- 후기
- JS
- ubuntu
- 면접
- 네비게이션
- scope
- 자바스크립트
- Express
- React
- Background
- navigation
- Python
- 디자인
- 알림
- 스코프
- 리액트
- 레이아웃
- 변수
- Today
- Total
어서와, 개발은 처음이지?
4.React Native State와 Props - 2부(Props) 본문
이 글은 4.React Native State와 Props - 1부(State)와 이어집니다
Props
props는 커스텀 컴포넌트와 관계가 깊습니다.
썩 와닿는 예는 아니지만 이번엔 사용자 별로 버튼을 각각 만든다고 가정해봅니다.
거두절미하고 코드부터 보시죠
일단 프로젝트 안에 TestComponent.js라는 파일을 만들고, 아래 코드를 붙여줍니다.
import React, { Component } from 'react'; import { View, Button, Text, } from 'react-native'; export default class TestComponent extends Component{ constructor(props){ super(props); } render(){ return( <View> <Text>{this.props.id}의 버튼</Text> <Button color={this.props.color} title={this.props.title} onPress={this.props.updateCount}/> </View> ) } }
그리고 App.js의 코드는 아래와 같이 바꿔줍니다.
import React, {Component} from 'react'; import {StyleSheet, Button, View} from 'react-native'; import TestComponent from './TestComponent'; const datas = [ {id:"gdHong",count:0,color:"red"}, {id:"ksYu",count:0,color:"green"}, {id:"ssLee",count:0,color:"blue"}, ]; type Props = {}; export default class App extends Component<Props> { constructor(props){ super(props); this.state={datas:datas}; } _updateCount(idx){ const newDatas = [...this.state.datas]; newDatas[idx].count = newDatas[idx].count + 1; // newArray[idx].count++; this.setState({datas:newDatas}); } render() { return ( <View style={styles.container}> { this.state.datas.map((data, index) => { return( <TestComponent key={data.id} id={data.id} color={data.color} title={data.count.toString()} updateCount={this._updateCount.bind(this, index)}/> ) }) } </View> ); } } const styles = StyleSheet.create({ container: { flex: 1, padding: 20, }, });
프로젝트를 실행하면 위와 같은 화면을 볼 수 있습니다.
일단 먼저 App.js 코드를 차근차근 짚어보죠.
import React, {Component} from 'react'; import {StyleSheet, Button, View} from 'react-native'; import TestComponent from './TestComponent'; const datas = [ {id:"gdHong",count:0,color:"red"}, {id:"ksYu",count:0,color:"green"}, {id:"ssLee",count:0,color:"blue"}, ]; type Props = {}; export default class App extends Component{ constructor(props){ super(props); this.state={datas:datas}; } . . . }
전체적인 맥락은 State의 예제 코드와 비슷합니다.
다만 사용자 별 버튼이 다르게 동작하는 것을 보여주기 위해 datas라는 배열을 초기화 했습니다.
커스텀 컴포넌트는 import TestComponent from './TestComponent'; 식으로 가져와서 사용할 수 있습니다.
'./TestComponent'는 실제 파일 명인 'TestComponent.js'를 뜻합니다.
TestComponent2.js로 이름이 바뀐다면 import TestComponent from './TestComponent2'; 라고 바꿔주시면 됩니다.
render() { return ( <View style={styles.container}> { this.state.datas.map((data, index) => { return( <TestComponent key={data.id} id={data.id} color={data.color} title={data.count.toString()} updateCount={this._updateCount.bind(this, index)}/> ) }) } </View> ); }
커스텀 컴포넌트 역시 Basic Component처럼 JSX 문법으로 사용할 수 있습니다.
map 함수를 사용해서 datas의 각 요소를 사용하여 TestComponent를 생성했으며, 이해하기 쉽게 쓰면 아래와 같습니다.
render() { const arr = []; for(let i=0; i<this.state.datas.length; i++){ let component = ( <TestComponent key={this.state.datas[i].id} id={this.state.datas[i].id} color={this.state.datas[i].color} title={this.state.datas[i].count.toString()} updateCount={this._updateCount.bind(this, i)} /> ); arr.push(component); } return ( <View style={styles.container}> { arr } </View> ); }
그리고 이것은 실제로 아래처럼 동작하게 됩니다
render() { return ( <View style={styles.container}> <TestComponent key={"gdHong"} id={"gdHong"} color={"red"} title={"0"} updateCount={this._updateCount.bind(this, 0)}/> <TestComponent key={"ksYu"} id={"ksYu"} color={"green"} title={"0"} updateCount={this._updateCount.bind(this, 1)}/> <TestComponent key={"ssLee"} id={"ssLee"} color={"blue"} title={"0"} updateCount={this._updateCount.bind(this, 2)}/> </View> ); }
다음은 TestComponent입니다.
import React, { Component } from 'react'; import { View, Button, Text, } from 'react-native'; export default class TestComponent extends Component{ constructor(props){ super(props); } render(){ return( <View> <Text>{this.props.id}의 버튼</Text> <Button color={this.props.color} title={this.props.title} onPress={this.props.updateCount}/> </View> ) } }
App.js에 비해 아주 간단해보이네요.
render()를 보시면 <Text>에 사용자 id를 나타내고 <Button>의 색과 글자를 입력해줍니다.
자세히보니 여기서 props가 나옵니다.
상위 컴포넌트에서 <TestComponent id= color= title= updateCount= />라고 넘긴 것들이
하위 컴포넌트에서 props.id props.color props.title props.updateCount라고 쓰여지게 되는 겁니다!
1.버튼을 누르면
2._updateCount(idx)가 호출되고
3.idx에 따른 state가 1 증가하게 되고
4.state가 변경됐기때문에 rerender가 일어나고
5.이에따라 props이 변경(props.title이 0 -> 1로 변경)되기 때문에 새로 그려지게 되는 것 입니다.
_updateCount(idx){ const newDatas = [...this.state.datas]; newDatas[idx].count = newDatas[idx].count + 1; // newArray[idx].count++; this.setState({datas:newDatas}); }
마지막으로 그냥 넘어가면 섭섭한, 함수에 대한 설명입니다.
원리는 간단합니다.
newDatas라는 배열에 State의 datas를 deep copy합니다.
그리고 idx에 해당하는 count를 추가한 뒤, setState()를 통해 새로 업데이트합니다.
idx는 updateCount={this._updateCount.bind(this. index)}에서
bind함수를 통해 index를 전달했습니다.
bind함수는 두번째 인자부터 그대로 함수에 전달됩니다.
updateCount={() => this._updateCount(index)} 처럼 넘겨주는 방법도 있습니다.
함수를 넘겨주는 패턴이 꽤 많아서 나중에 다시 설명하겠습니다.
요약
* 사전지식 - JSX 안에서 javascript 객체(값)를 사용할때는 {}로 감싸서 전달한다.
* props, state가 변경될때마다 render()가 새로 일어난다.
* state에는 현재 화면과 관련된 가변 값을 주로 담는다.
* props에는 상위 컴포넌트에서 전달 받은 값이 들어있다.
마치며
드디어 지겨운 이론공부는 끝이 났습니다.
이제 React Native 앱개발에 필요한 기초 이론은 모두 습득하셨습니다.
다음부터는 UI를 작업과 함께 앱 만들기를 시작해보겠습니다.
Comming Soon!
'React > React Native' 카테고리의 다른 글
5.React Native 레이아웃 디자인 - 2부 배치(Flex Direction)와 정렬(justify content, align items) (16) | 2018.07.26 |
---|---|
5.React Native 레이아웃 디자인 - 1부 flex와 width, height (11) | 2018.07.24 |
4.React Native State와 Props - 1부(State) (6) | 2018.07.23 |
3.React Native App.js와 JSX (4) | 2018.07.22 |
2.React Native 프로젝트 기본 구조, 디버깅 (11) | 2018.07.15 |