본격적으로 React Native로 개발에 앞서 DOCS를 살펴보니 아무래도 리액트를 기반으로 작동을 하다보니 비슷한게 많았다.
취업 전 프론트 교육을 받을 때 컴포넌트는 부품을 뜻하며 React의 가장 큰 특징이라고 배웠다. 리액트는 코드를 컴포넌트화(부품화)하여 필요한 곳에서 적절하게 불러와 사용이 가능한 만큼 재사용성이 크다는게 특징이었다.
이와 마찬가지로 RN에서도 컴포넌트화하여 코드의 재사용성이 크다는 특징이 있었다. 작성법은 리액트와 크게 다르지 않으며 아래와 같다.
import React from 'react';
import {Text} from 'react-native';
const Cat = () => {
return <Text>Hello, I am your cat!</Text>;
};
export default Cat;
위의 코드는 자바스크립트를 사용하여 리액트와 리액트 네이티브의 핵심 컴포넌트인 Text를 import하여 정의하였고, 익명함수를 사용하여 cat 컴포넌트를 나타냈다. cat 컴포넌트는 Text를 반환하고 이를 export default를 통해 cat 컴포넌트를 화면에 뿌려준다. 그러면 아래와 같이 확인이 가능하다.
리액트와 리액트 네이티브 모두 JSX를 사용한다. JSX는 Javascript + XML의 약자로, 말그대로 자바스크립트와 XML이 합쳐진 Javascript의 확장 문법이다. 이는 리액트와 리액트 네이티브에서 UI를 작성할 때 자바스크립트 코드 안에 HTML과 유사한 구조를 사용할 수 있도록 하는 것이 주된 목적이다.
import React from 'react';
import {Text} from 'react-native';
const Cat = () => {
const name = 'Maru';
return <Text>Hello, I am {name}!</Text>;
};
export default Cat;
위의 예시는 name이라는 변수를 선언한 후 중괄호로 감싸 JSX 안에 사용하였다. 이처럼 JSX의 중괄호 안에는 유효한 모든 Javascript 표현식을 넣을 수 있다. 이와 같이 보다 직관적이고 가독성이 좋은 코드를 작성할 수 있다.
import React from 'react';
import {Text} from 'react-native';
const getFullName = (
firstName: string,
secondName: string,
thirdName: string,
) => {
return firstName + ' ' + secondName + ' ' + thirdName;
};
const Cat = () => {
return <Text>Hello, I am {getFullName('Rum', 'Tum', 'Tugger')}!</Text>;
};
export default Cat;
getFullName 컴포넌트에 firstName, secondName, thirdName을 파라미터로 받고 이를 리턴해주는 컴포넌트를 만들어서 Cat 컴포넌트에서 jsx를 사용하여 Cat 컴포넌트를 리턴하여 화면에 그려주는 방식도 가능하다.
처음 리액트를 사용하여 프론트를 개발할 때 프롭스를 다른 컴포넌트로 넘겨주면 된다고 하였는데 그때는 아무것도 모르고 그냥 넘기라니까 넘겼었다. 그리고 리액트 네이티브를 보며 공부한 props는 properties의 약자로 컴포넌트에 전달되는 속성 값이라고 한다. 크게 와닿는 문장은 아니지만 안드로이드 개발로 따지면 intent로 액티비티 간에 데이터를 옮기는 것 아니면 뭔가 확장된 변수의 느낌이다.
import React from 'react';
import {Text, View} from 'react-native';
type CatProps = {
name: string;
};
const Cat = (props: CatProps) => {
return (
<View>
<Text>Hello, I am {props.name}!</Text>
</View>
);
};
const Cafe = () => {
return (
<View>
<Cat name="Maru" />
<Cat name="Jellylorum" />
<Cat name="Spot" />
</View>
);
};
export default Cafe;
위의 코드는 CatProps를 name: String으로 지정해주어 Cat 컴포넌트에서 파라미터로 사용되어 Text를 반환하고 있다. 이러한 구조를 통해 Cafe 컴포넌트에서 Cat 컴포넌트를 불러와 name="Maru" 와 같은 형식으로 프롭스를 지정하여 아래와 같이 출력한다.
State는 컴포넌트 자체의 데이터 보관소이다. 사용자의 액션에 따라 변하는 값을 다루기 편하고 useState()를 사용하여 나타낸다.
import React, {useState} from 'react';
import {Button, Text, View} from 'react-native';
type CatProps = {
name: string;
};
const Cat = (props: CatProps) => {
const [isHungry, setIsHungry] = useState(true);
return (
<View>
<Text>
I am {props.name}, and I am {isHungry ? 'hungry' : 'full'}!
</Text>
<Button
onPress={() => {
setIsHungry(false);
}}
disabled={!isHungry}
title={isHungry ? 'Pour me some milk, please!' : 'Thank you!'}
/>
</View>
);
};
const Cafe = () => {
return (
<>
<Cat name="Munkustrap" />
<Cat name="Spot" />
</>
);
};
export default Cafe;
전체적인 코드는 위와 같다.
다만 조금 더 설명을 붙이자면
const Cat = (props: CatProps) => {
const [isHungry, setIsHungry] = useState(true);
// ...
};
useState를 import하여 isHungry state를 정의한다. 그리고 버튼을 누르면 setState의 상태가 변하도록 코딩을 하여 변경된 값을 나타낼 수 있게 해주면 된다.
<Button
onPress={() => {
setIsHungry(false);
}}
//..
/>