어서와, 개발은 처음이지?

4.React Native State와 Props - 2부(Props) 본문

React/React Native

4.React Native State와 Props - 2부(Props)

오지고지리고알파고포켓몬고 2018. 7. 23. 16:00
반응형



이 글은 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!

Comments