분류 Reactjs

React Native 시작하기

컨텐츠 정보

  • 조회 278 (작성일 )

본문

스마트 폰의 인기가 계속 높아짐에 따라 개발자는 모바일 애플리케이션 구축을 위한 솔루션을 찾고 있습니다. 

웹 배경이 있는 개발자의 경우 Cordova 및 Ionic, React Native, NativeScript 및 Flutter와 같은 프레임 워크를 통해 HTML, XML, CSS 및 JavaScript와 같은 이미 익숙한 언어로 모바일 앱을 만들 수 있습니다.


이 가이드에서는 React Native에 대해 자세히 살펴 보겠습니다. 시작하기 위한 절대적인 기본 사항을 배우게 됩니다. 구체적으로 다음 내용을 다룹니다.


  • React Native 란
  • 엑스포 란?
  • Expo를 사용하여 React Native 개발 환경을 설정하는 방법
  • React Native로 앱을 만드는 방법

전제 조건 


이 가이드에서는 사용자가 웹 개발 배경이라고 가정합니다. 이 튜토리얼을 자신 있게 따라 할 수 있는 최소 요구 사항은 HTML, CSS 및 JavaScript를 알아야 합니다. 또한 운영 체제에 소프트웨어를 설치하고 명령 줄을 사용하는 방법을 알아야 합니다. ES6 구문도 사용할 예정이므로 기본 ES6 구문도 알고 있다면 도움이 될 것입니다. React에 대한 지식은 도움이 되지만 필수는 아닙니다.


https://www.sitepoint.com/getting-started-with-react-native/


React Native는 무엇입니까? 


React Native는 Android와 iOS에서 모두 작동하는 앱을 빌드하기 위한 프레임 워크입니다. 

JavaScript 및 React를 사용하여 실제 네이티브 앱을 만들 수 있습니다. 이는 HTML을 사용하여 UI를 빌드 한 다음 기기의 통합 모바일 브라우저 (WebView) 내에 표시되는 Cordova와 같은 프레임 워크와 다릅니다. React Native에는 네이티브 UI 구성 요소로 컴파일 되는 기본 제공 구성 요소가 있으며 JavaScript 코드는 가상 머신을 통해 실행됩니다. 이것은 React Native를 Cordova보다 더 성능 있게 만듭니다.


React Native의 또 다른 장점은 기본 장치 기능에 액세스 할 수 있다는 것입니다. 카메라다양한 장치 센서와 같은 기본 장치 기능에 액세스하는 데 사용할 수 있는 많은 플러그인이 있습니다. 아직 구현되지 않은 플랫폼 별 기능이 필요한 경우 고유 한 네이티브 모듈을 빌드 할 수도 있습니다.이를 위해서는 지원하려는 네이티브 플랫폼 (자바 또는 Kotlin)에 대한 상당한 지식이 필요합니다. Android의 경우, Objective C 또는 iOS의 경우 Swift).


여기에 와서 React를 처음 사용한다면 그것이 무엇인지 궁금 할 것입니다. React는 사용자 인터페이스를 구축하기 위한 웹용 JavaScript 라이브러리입니다. MVC에 익숙하다면 기본적으로 MVC의보기입니다. React의 주요 목적은 개발자가 재사용 가능한 UI 구성 요소를 구축 할 수 있도록 하는 것입니다. 이러한 구성 요소의 예로는 단추, 슬라이더 및 카드가 있습니다. React Native는 재사용 가능한 UI 구성 요소를 구축한다는 아이디어를 모바일 앱 개발에 도입했습니다.


엑스포 란? 


여기에 오기 전에 Expo에 대해 들어 보셨을 것입니다. 공식 React Native 문서에도 언급되어 있으므로 이것이 무엇인지 궁금 할 것입니다.


간단히 말해서 Expo를 사용하면 개발 환경을 설정하는 데 따르는 초기 문제 없이 React Native 앱을 빌드 할 수 있습니다. 컴퓨터에 Node가 설치되어 있고 장치 또는 에뮬레이터에 Expo 클라이언트 앱이 설치되어 있으면 됩니다.


하지만 이것이 Expo가 처음에 판매되는 방식입니다. 실제로는 그 이상입니다. Expo는 실제로 React Native로 Android 및 iOS 앱을 더 빠르게 빌드하기 위한 도구, 라이브러리 및 서비스에 대한 액세스를 제공하는 플랫폼입니다. Expo에는 모바일 앱 개발 플랫폼에서 요청할 수 있는 대부분의 API가 포함 된 SDK가 함께 제공됩니다.


Expo로 React Native 앱을 빌드 하기 시작하면 바로 액세스 할 수 있는 API 중 일부에 불과합니다. 물론 이러한 API는 표준 React Native 설정을 사용하여 앱을 개발하는 경우 기본 모듈을 통해서도 사용할 수 있습니다.


Plain React Native 또는 Expo? 


진짜 질문은 어떤 것을 선택해야 하는가 입니다. 일반 React Native 또는 Expo? 정말 정답이나 오답이 없습니다. 그것은 모두 상황과 당신의 요구에 달려 있습니다. 하지만 React Native를 빨리 시작하고 싶기 때문에 이 튜토리얼을 읽고 있다고 가정하는 것이 안전하다고 생각합니다. 그래서 계속해서 Expo부터 시작하는 것이 좋습니다. 빠르고 간단하며 쉽게 설정할 수 있습니다. React Native 코드를 직접 수정하고 몇 시간 만에 제공해야 하는 것을 느낄 수 있습니다.


그러나 다른 개념을 이해하기 시작하고 다른 기본 기능에 대한 필요성이 발생함에 따라 Expo가 제한적이라는 것을 알 수 있습니다. 예, 사용 가능한 많은 기본 기능이 있지만 표준 React Native 프로젝트에서 사용할 수 있는 모든 기본 모듈이 지원되는 것은 아닙니다.


참고 : unimodules와 같은 프로젝트는 개발자가 React Native와 ExpoKit 모두에서 작동하는 네이티브 모듈을 만들 수 있도록 허용하기 때문에 표준 React Native 프로젝트와 Expo 프로젝트 간의 격차를 좁히기 시작했습니다.


React Native 개발 환경 설정 


React Native를 빠르게 시작하기 위해 권장되는 방법은 Expo를 설정하는 것입니다.


Expo를 설정하기 위한 유일한 전제 조건은 컴퓨터에 Node.js가 설치되어 있어야 한다는 것입니다. 이를 위해 공식 Node 다운로드 페이지로 이동하여 시스템의 관련 바이너리를 가져 오거나 버전 관리자를 사용하여 여러 버전의 Node를 설치하고 원하는 대로 전환 할 수 있습니다.


Node.js가 설치되면 Expo CLI를 설치하십시오. 프로젝트를 생성, 제공, 패키징 및 게시하는 데 사용됩니다.


npm install -g expo-cli

다음으로 Expo의 기본 패키지 관리자 인 Yarn을 설치합니다.


npm install -g yarn

그게 전부입니다! 다음 단계는 Android 또는 iOS 용 Expo 클라이언트 앱을 다운로드하는 것입니다. 이것이 개발 중에 Expo 앱을 실행할 수 있는 유일한 방법입니다. 앱을 배송 할 준비가 되면 이 가이드에 따라 iOS 및 Android 용 독립 실행 형 바이너리를 만들어 Apple App Store 및 Google Play Store에 제출할 수 있습니다.


우리가 구축 할 것 


이제 개발 환경이 설정되었으므로 만들 앱인 Pokémon 검색 앱을 볼 수 있습니다. 사용자는 외부 API에서 Pokémon의 세부 정보를 가져 와서 사용자에게 표시하기 전에 입력 상자에 Pokémon의 이름을 입력 할 수 있습니다.


완성 된 모습은 다음과 같습니다.


Pokémon Search App 


그 어느 때보다 GitHub 저장소에서 이에 대한 소스 코드를 찾을 수 있습니다.


앱 부트 스트랩 


터미널에서 다음 명령을 실행하여 Expo를 사용하여 새 React Native 프로젝트를 만듭니다.


expo init RNPokeSearch

관리 워크 플로에서 공백을 선택합니다. 기본적으로 Yarn을 사용하여 종속성을 설치합니다.


expo init 


이 관리 워크 플로 및 베어 워크 플로가 무엇인지 물어볼 수 있습니다. Expo가 지원하는 두 가지 유형의 워크 플로입니다. 관리 워크 플로를 사용하면 JavaScript 만 다루면 Expo가 모든 것을 관리합니다. Bare 워크 플로에서 네이티브 코드를 완전히 제어 할 수 있습니다. React Native CLI와 동일한 자유를 제공하지만 Expo의 라이브러리 및 서비스가 추가되었습니다. Expo의 워크 플로에 대해 자세히 알아 보려면 이 관리 형 및 베어 소개 페이지를 방문 할 수 있습니다.


웹 환경과 마찬가지로 라이브러리를 설치하여 React Native에서 다양한 기능을 쉽게 구현할 수 있습니다. 프로젝트가 생성되면 pokemon과 axios의 두 가지 종속성을 설치해야 합니다. 전자는 검색 창에 입력 한 텍스트가 실제 Pokémon 이름인지 확인하는 데 사용되며 axios는 사용 중인 API, 즉 PokeAPI에 대한 HTTP 요청을 만드는 데 사용됩니다.


yarn add pokemon axios

React Native 프로젝트 디렉토리 구조 


코딩을 진행하기 전에 먼저 Expo로 만든 React Native 프로젝트의 디렉터리 구조를 살펴 보겠습니다.


Expo project directory 


기억해야 할 가장 중요한 파일과 폴더는 다음과 같습니다.


  • App.js : 기본 프로젝트 파일입니다. 여기에서 앱 개발을 시작합니다. 이 파일에 대한 모든 변경 사항은 화면에 반영됩니다.
  • src : 앱 자체와 관련된 모든 소스 코드를 저장하는 메인 폴더 역할을 합니다. Expo CLI에서 만든 기본 프로젝트에는 포함되지 않습니다. 이 폴더의 이름은 무엇이든 될 수 있습니다. 어떤 사람들은 앱도 사용합니다.
  • assets : 아이콘 및 스플래시 화면과 같은 앱 자산이 저장되는 위치입니다.
  • package.json : 여기서 이 프로젝트를 위해 설치 한 라이브러리의 이름과 버전이 추가됩니다.
  • node_modules : 설치 한 라이브러리가 저장되는 위치. 이전에 두 라이브러리를 설치하기 전에 여기에는 이미 많은 폴더가 포함되어 있습니다. React Native에도 자체 종속성이 있기 때문입니다. 설치하는 다른 모든 라이브러리도 마찬가지입니다.

지금은 나머지 폴더와 파일은 신경 쓰지 마세요. 시작할 때 필요하지 않기 때문입니다.


앱 실행 


이제 아래 명령을 실행하여 앱을 실행할 수 있습니다. 휴대 전화에 해당하는 Expo 클라이언트 (Android 또는 iOS)를 이미 설치했는지, 설치하기 전에 컴퓨터와 동일한 네트워크에 연결되어 있는지 확인하세요. 테스트 할 수 있는 Android 또는 iOS 기기가 없는 경우 Android 스튜디오 에뮬레이터 또는 iOS 시뮬레이터를 사용하여 컴퓨터에서 앱을 실행할 수 있습니다.


yarn start

실행되면 QR 코드가 표시됩니다.


Expo yarn start 


Expo 클라이언트 앱을 열고 프로젝트 탭에서 QR 코드 스캔을 클릭합니다. Android 또는 iOS 기기에서 앱이 열립니다. 에뮬레이터가 실행 중인 경우 i를 눌러 iOS 시뮬레이터에서 실행하거나 a를 눌러 Android 에뮬레이터에서 실행할 수 있습니다.


Expo client app 


실제 기기에서 테스트하는 경우 개발자 메뉴가 표시되도록 흔들어주세요.


React Native developer settings 


빠른 새로 고침이 활성화되어 있는지 확인하십시오. 이렇게 하면 구성 요소에 대한 변경 사항을 자동으로 다시 로드 할 수 있습니다.


앱 코딩 


Expo에는 원하는 것을 수행하는 데 사용할 수 있는 많은 내장 구성 요소가 있습니다. API 문서를 살펴보면 필요한 구현 방법에 대한 정보를 찾을 수 있습니다. 대부분의 경우 특정 UI 구성 요소 또는 사용하려는 서비스와 함께 작동하는 SDK가 필요합니다. 대부분의 경우 워크 플로는 다음과 같이 표시됩니다.


  • 원하는 것을 구현하는 기존 패키지를 찾으십시오.
  • 그것을 설치하십시오.
  • 링크하십시오. 이는 Expo의 베어 워크 플로를 사용 중이고 설치 한 패키지에 해당하는 기본 종속성이 있는 경우에만 필요합니다.
  • 프로젝트에서 사용하십시오.

이제 환경을 설정하고 워크 플로에 대해 약간 배웠으므로 앱 코딩을 시작할 준비가 되었습니다.


먼저 필요한 파일을 스캐 폴드 해 보겠습니다. 이는 src / Main.js 및 src / components / Pokemon.js입니다. Main 구성 요소는 검색 입력을 표시하고 API를 쿼리 하는 코드를 보유하는 반면 Pokemon 구성 요소는 반환 된 Pokémon 데이터를 표시하는 데 사용됩니다.


mkdir -p src/components
touch src/Main.js
touch src/components/Pokemon.js

두 파일에 더미 콘텐츠를 추가합니다.


// src/Main.js
import React, { Component } from 'react';

export default class Main extends Component {
  render() {
    return null;
  }
}
// src/components/Pokemon.js
import  React  from  'react';

const  Pokemon  =  ()  =>  null;

다음으로 App.js 파일의 내용을 다음 코드로 바꿉니다.


import React from 'react';
import Main from './src/Main';

function App() {
  return <Main />;
}

export default App;

위 코드의 첫 번째 줄은 React를 가져옵니다. 구성 요소를 만들 때마다 이 클래스를 가져와야 합니다.


두 번째 줄은 사용자 정의 Main 구성 요소를 가져 오는 곳입니다. 나중에 입력 하겠지만 지금은 여기에 대부분의 코드를 넣을 것입니다.


그 후 새로운 기능을 생성하여 컴포넌트를 생성합니다. 이 함수가 하는 일은 주 구성 요소를 반환하는 것입니다.


마지막으로 Expo에서 가져오고 렌더링 할 수 있도록 클래스를 내 보냅니다.


다음으로 src / Main.js 파일에 다음을 추가합니다.


// src/Main.js
import React, { Component } from 'react';
import {
  SafeAreaView,
  View,
  Text,
  TextInput,
  Button,
  Alert,
  StyleSheet,
  ActivityIndicator,
} from 'react-native';

두 번째 줄은 React Native에 내장 된 구성 요소를 가져옵니다. 각각의 역할은 다음과 같습니다.


  • SafeAreaView : 장치의 안전 영역 경계 내에서 콘텐츠를 렌더링 합니다. 이렇게 하면 콘텐츠를 래핑하는 패딩이 자동으로 추가되어 기기의 카메라 노치 및 센서 하우징 영역에 렌더링 되지 않습니다.
  • View : 기본 UI 구성 요소입니다. 이는 주로 다른 모든 구성 요소의 래퍼로 사용되므로 쉽게 스타일을 지정할 수 있는 방식으로 구성됩니다. <div>와 동등하다고 생각하십시오. Flexbox를 사용하려면 이 구성 요소를 사용해야 합니다.
  • Text : 텍스트를 표시합니다.
  • TextInput : 텍스트 입력을 위한 UI 구성 요소입니다. 이 텍스트는 일반 텍스트, 이메일, 비밀번호 또는 숫자 패드 일 수 있습니다.
  • Button : 플랫폼 별 버튼을 표시합니다. 이 구성 요소는 실행되는 플랫폼에 따라 다르게 보입니다. Android라면 머티리얼 디자인을 사용합니다. iOS라면 Cupertino를 사용합니다.
  • Alert : 경고 및 프롬프트를 표시합니다.
  • ActivityIndicator : 로딩 애니메이션 표시기를 표시합니다.
  • StyleSheet : 구성 요소 스타일을 정의합니다.

다음으로 앞서 설치 한 라이브러리를 가져옵니다.


import axios from 'axios';
import pokemon from 'pokemon';

Pokémon 데이터를 표시하는 데 사용되는 사용자 지정 Pokemon 구성 요소 :


import Pokemon from "./components/Pokemon";

참고 : Expo가 Pokemon (또는 기타) 구성 요소를 확인할 수없는 경우 서버를 다시 시작하십시오.


필요한 Pokémon 데이터를 가져 오는 데는 두 개의 API 요청이 필요하므로 API의 기본 URL을 상수로 설정해야 합니다.


const POKE_API_BASE_URL = 'https://pokeapi.co/api/v2';

다음으로 구성 요소 클래스를 정의하고 상태를 초기화합니다.


export default class Main extends Component {
  constructor(props) {
    super(props)

    this.state = {
      isLoading: false, // decides whether to show the activity indicator or not
      searchInput: '', // the currently input text
      name: '', // Pokémon name
      pic: '', // Pokémon image URL
      types: [], // Pokémon types array
      desc: '', // Pokémon description
    };
  }

  render() {
    return null;
  }
}

위 코드에서 우리는 앱의 주요 구성 요소를 정의하고 있습니다. ES6 클래스를 정의하고 React의 Component 클래스를 확장하면 됩니다. 이것은 React에서 컴포넌트를 정의하는 또 다른 방법입니다. App.js 파일에서 기능 구성 요소를 만들었습니다. 이번에는 클래스 기반 구성 요소를 만듭니다.


이 둘의 주요 차이점은 기능적 구성 요소가 프레젠테이션 목적으로 만 사용된다는 것입니다. 기능적 구성 요소는 필요한 모든 데이터가 소품을 통해 전달되기 때문에 자체 상태를 유지할 필요가 없습니다. 반면에 클래스 기반 구성 요소는 자체 상태를 유지하며 일반적으로 기능 구성 요소에 데이터를 전달하는 구성 요소입니다. 이것이 React에서 컴포넌트를 생성하는 전통적인 방법입니다. 보다 현대적인 접근 방식은 기능적 구성 요소를 고수하고 상태 후크를 사용하여 상태를 관리하는 것입니다.하지만 이 자습서에서는 단순하게 유지하고 클래스 기반 구성 요소를 고수 할 것입니다.


함수형 구성 요소와 클래스 기반 구성 요소의 차이점에 대해 자세히 알아 보려면“React의 Functional vs Class-Components”자습서를 읽어보십시오.


코드로 돌아가서 컴포넌트 내부의 상태를 초기화합니다. 일반 JavaScript 객체로 정의합니다. 상태가 되는 모든 데이터는 구성 요소에서 렌더링 되는 내용을 변경해야 합니다. 이 경우 활동 표시기의 가시성을 제어하기 위해 isLoading을, 검색 상자의 입력 값을 추적하기 위해 searchInput을 넣습니다.


이것은 기억해야 할 중요한 개념입니다. React Native의 기본 제공 구성 요소와 사용자가 만든 사용자 지정 구성 요소는 다음을 제어하는 ​​속성을 허용합니다.


  • 화면에 표시되는 내용 (데이터 소스)
  • 제시 방법 (구조)
  • 어떻게 생겼는지 (스타일)
  • 사용자가 상호 작용할 때 수행 할 작업 (함수)

다음 섹션에서 이러한 속성에 대해 자세히 살펴 보겠습니다. 지금은 이러한 속성의 값이 일반적으로 상태를 통해 업데이트 됩니다.


나머지 상태 값은 Pokémon 데이터에 대한 것입니다. 나중에 저장할 것으로 예상되는 것과 동일한 유형의 데이터로 초기 값을 설정하는 것이 좋습니다. 이는 문서로도 사용되기 때문입니다.


구성 요소 구조 및 스타일 지정 


컴포넌트 클래스 정의로 돌아가 보겠습니다. React의 Component 클래스를 확장 할 때 render () 메서드를 정의해야 합니다. 여기에는 구성 요소의 UI를 반환하는 코드가 포함되며 이전에 가져온 React Native 구성 요소로 구성됩니다.


각 구성 요소에는 고유 한 소품 세트가 있습니다. 이들은 기본적으로 컴포넌트의 특정 측면을 제어하기 위해 컴포넌트에 전달하는 속성입니다. 아래 코드에서 대부분은 컴포넌트의 스타일을 수정하는 데 사용되는 스타일 소품을 가지고 있습니다. 모든 데이터 유형을 소품으로 전달할 수 있습니다. 예를 들어, TextInput의 onChangeText prop은 함수이고 Pokemon의 유형 prop은 객체의 배열입니다. 나중에 Pokemon 구성 요소에서 소품이 어떻게 사용되는지 볼 수 있습니다.


Main.js의 render() 메서드를 다음으로 바꿉니다.


render() {
  const { name, pic, types, desc, searchInput, isLoading } = this.state; // extract the Pokémon data from the state

  return (
    <SafeAreaView style={styles.wrapper}>
      <View style={styles.container}>
        <View style={styles.headContainer}>
          <View style={styles.textInputContainer}>
            <TextInput
              style={styles.textInput}
              onChangeText={(searchInput) => this.setState({ searchInput })}
              value={this.state.searchInput}
              placeholder="Search Pokémon"
            />
          </View>
          <View style={styles.buttonContainer}>
            <Button
              onPress={this.searchPokemon}
              title="Search"
              color="#0064e1"
            />
          </View>
        </View>

        <View style={styles.mainContainer}>
          {isLoading && <ActivityIndicator size="large" color="#0064e1" />}

          {!isLoading && (
            <Pokemon name={name} pic={pic} types={types} desc={desc} />
          )}
        </View>
      </View>
    </SafeAreaView>
  );
}

위의 코드를 분석하여 먼저 상태 데이터를 추출합니다.


const { name, pic, types, desc, searchInput, isLoading } = this.state;

다음으로 다음 구조를 따르는 구성 요소의 UI를 반환합니다.


SafeAreaView.wrapper;
  View.container;
    View.headContainer;
      View.textInputContainer;
        TextInput;
      View.buttonContainer;
        Button;
    View.mainContainer;
      ActivityIndicator;
        Pokemon;

위 구조는 Flexbox 사용에 최적화되어 있습니다. 계속해서 파일 하단에서 구성 요소 스타일을 정의하십시오.


const styles = StyleSheet.create({
  wrapper: {
    flex: 1,
  },
  container: {
    flex: 1,
    padding: 20,
    backgroundColor: '#F5FCFF',
  },
  headContainer: {
    flex: 1,
    flexDirection: 'row',
    marginTop: 100,
  },
  textInputContainer: {
    flex: 2,
  },
  buttonContainer: {
    flex: 1,
  },
  mainContainer: {
    flex: 9,
  },
  textInput: {
    height: 35,
    marginBottom: 10,
    borderColor: '#ccc',
    borderWidth: 1,
    backgroundColor: '#eaeaea',
    padding: 5,
  },
});

React Native에서는 StyleSheet.create()를 사용하고 스타일이 포함 된 객체를 전달하여 스타일을 정의합니다. 이러한 스타일 정의는 기본적으로 JavaScript 객체이며 일반적인 CSS 스타일과 동일한 구조를 따릅니다.


element: {
  property: value;
}

래퍼와 컨테이너는 flex : 1로 설정됩니다. 즉, 형제가 없기 때문에 사용 가능한 공간 전체를 차지합니다. React Native의 기본값은 flexDirection : 'column'입니다. 즉, flex 항목을 세로로 배치합니다.


flex direction column 


반대로 (flexDirection : 'row')는 항목을 가로로 배치합니다.

flex direction row 


headContainer와는 다릅니다. flex : 1로 설정되어 있어도 mainContainer가 형제로 설정되어 있기 때문입니다. 이것은 headContainer와 mainContainer가 모두 같은 공간을 공유한다는 것을 의미합니다. mainContainer는 flex : 9로 설정되어 사용 가능한 공간의 대부분 (약 90 %)을 차지하지만 headContainer는 약 10 % 만 차지합니다.


headContainer의 내용으로 이동하겠습니다. 자식으로 textInputContainer 및 buttonContainer가 있습니다. flexDirection : 'row'로 설정되어 자식이 가로로 배치됩니다. 공간 공유에 대해서도 동일한 원칙이 적용됩니다. textInputContainer는 사용 가능한 수평 공간의 2/3를 차지하고 buttonContainer는 1/3 만 차지합니다.


나머지 스타일은 CSS 배경이 있을 때 꽤 자명합니다. 생략하고 다음 문자를 대문자로 설정하십시오. 예를 들어 background-color를 설정하려는 경우 React Native에 해당하는 것은 backgroundColor입니다.


참고 : 웹에서 사용할 수 있는 모든 CSS 속성이 React Native에서 지원되는 것은 아닙니다. 예를 들어 부동 또는 표 속성과 같은 것은 지원되지 않습니다. 보기텍스트 구성 요소에 대한 문서에서 지원되는 CSS 속성 목록을 찾을 수 있습니다. 누군가 React Native Styling Cheat Sheet를 컴파일했으며 사용하려는 특정 React Native 구성 요소에 대한 문서에 스타일 섹션이 있습니다. 예를 들어 다음은 이미지 구성 요소에 사용할 수 있는 스타일 속성입니다.


이벤트 처리 및 상태 업데이트 


이제 TextInput 및 Button 구성 요소에 대한 코드를 분석해 보겠습니다. 이 섹션에서는 React Native에서 이벤트 처리, HTTP 요청 및 상태 업데이트에 대해 설명합니다.


TextInput의 코드를 살펴 보겠습니다.


<TextInput
  style={styles.textInput}
  onChangeText={(searchInput) => this.setState({ searchInput })}
  value={this.state.searchInput}
  placeholder="Search Pokémon"
/>

위 코드에서는 사용자가 컴포넌트에 무언가를 입력 할 때 실행할 함수를 설정합니다. 이와 같은 이벤트 처리는 DOM에서 처리되는 방법과 유사합니다. 이벤트 이름을 소품으로 전달하고 실행하려는 함수에 값을 설정하기 만하면 됩니다. 이 경우 상태를 업데이트하는 중이므로 인라인 처리합니다. 사용자가 입력 한 값은 자동으로 제공하는 함수에 인수로 전달되므로 해당 값으로 상태를 업데이트하기 만하면 됩니다. TextInput의 값을 상태 변수의 값으로 설정하는 것을 잊지 마십시오. 그렇지 않으면 사용자가 입력 한 값이 입력 할 때 표시되지 않습니다.


다음으로 Button 구성 요소로 이동합니다. 여기에서는 onPress 이벤트를 수신합니다.


<Button onPress={this.searchPokemon} title="Search" color="#0064e1" />

누르면 searchPokemon () 함수가 실행됩니다. render () 메서드 바로 아래에 이 함수를 추가합니다. 이 함수는 HTTP 요청을 수행하는 것이 비동기 작업이므로 async ... await 패턴을 사용합니다. Promises를 사용할 수도 있지만 코드를 간결하게 유지하기 위해 대신 async / await를 사용합니다. 이 기술에 익숙하지 않은 경우 "현대 JS의 흐름 제어"를 읽어보십시오.


// src/Main.js
import React, { Component } from 'react';
...
export default class Main extends Component {
  ...

  render() { ... }

  searchPokemon = async () => {
    try {
      const pokemonID = pokemon.getId(this.state.searchInput); // check if the entered Pokémon name is valid

      this.setState({
        isLoading: true, // show the loader while request is being performed
      });

      const { data: pokemonData } = await axios.get(
        `${POKE_API_BASE_URL}/pokemon/${pokemonID}`
      );
      const { data: pokemonSpecieData } = await axios.get(
        `${POKE_API_BASE_URL}/pokemon-species/${pokemonID}`
      );

      const { name, sprites, types } = pokemonData;
      const { flavor_text_entries } = pokemonSpecieData;

      this.setState({
        name,
        pic: sprites.front_default,
        types: this.getTypes(types),
        desc: this.getDescription(flavor_text_entries),
        isLoading: false, // hide loader
      });
    } catch (err) {
      Alert.alert('Error', 'Pokémon not found');
    }
  };
}

const styles = StyleSheet.create({ ... });

위의 코드를 분석하여 입력 한 포켓몬 이름이 유효한지 먼저 확인합니다. 유효하면 National Pokedex ID (링크를 열면 Pokémon 이름 위에 있는 번호)가 반환되고 HTTP 요청에 대한 매개 변수로 제공됩니다. HTTP GET 요청에 해당하는 axios의 get () 메서드를 사용하여 요청이 이루어집니다. 데이터를 사용할 수 있게 되면 필요한 것을 추출하고 상태를 업데이트합니다.


다음은 getTypes () 함수입니다. Pokémon 유형의 슬롯 및 유형 속성을 id 및 이름에 다시 할당하기 만하면 됩니다.


getTypes = (types) =>
  types.map(({ slot, type }) => ({
    id: slot,
    name: type.name,
  }));

다음은 getDescription () 함수입니다. 이것은 flavor_text의 첫 번째 영어 버전을 찾습니다.


getDescription = (entries) =>
    entries.find((item) => item.language.name === 'en').flavor_text;

다음과 같이 searchPokemon 함수 뒤에 추가합니다.


import React, { Component } from 'react';
...
export default class Main extends Component {
  ...

  render() { ... }

  searchPokemon = async () => { ... };
  getTypes = (types) => types.map( ... );
  getDescription = (entries) => entries.find( ... );
}

const styles = StyleSheet.create({ ... });

Pokémon Component 


이제 앱이 API에서 데이터를 가져 오므로 앞서 살펴본 Pokemon 구성 요소를 확장하여 해당 데이터를 표시 할 수 있습니다. src / components / Pokemon.js 파일을 열고 내용을 다음으로 바꿉니다.


import React from 'react';
import { View, Text, Image, FlatList, StyleSheet } from 'react-native';

const Pokemon = ({ name, pic, types, desc }) => {
  if (!name) {
    return null;
  }

  return (
    <View style={styles.mainDetails}>
      <Image source={{ uri: pic }} style={styles.image} resizeMode="contain" />
      <Text style={styles.mainText}>{name}</Text>

      <FlatList
        columnWrapperStyle={styles.types}
        data={types}
        numColumns={2}
        keyExtractor={(item) => item.id.toString()}
        renderItem={({ item }) => (
          <View style={[styles[item.name], styles.type]}>
            <Text style={styles.typeText}>{item.name}</Text>
          </View>
        )}
      />

      <View style={styles.description}>
        <Text>{desc}</Text>
      </View>
    </View>
  );
};

//
const styles = StyleSheet.create({
  mainDetails: {
    padding: 30,
    alignItems: 'center',
  },
  image: {
    width: 100,
    height: 100,
  },
  mainText: {
    fontSize: 25,
    fontWeight: 'bold',
    textAlign: 'center',
  },
  description: {
    marginTop: 20,
  },
  types: {
    flexDirection: 'row',
    marginTop: 20,
  },
  type: {
    padding: 5,
    width: 100,
    alignItems: 'center',
  },
  typeText: {
    color: '#fff',
  },
  normal: {
    backgroundColor: '#8a8a59',
  },
  fire: {
    backgroundColor: '#f08030',
  },
  water: {
    backgroundColor: '#6890f0',
  },
  electric: {
    backgroundColor: '#f8d030',
  },
  grass: {
    backgroundColor: '#78c850',
  },
  ice: {
    backgroundColor: '#98d8d8',
  },
  fighting: {
    backgroundColor: '#c03028',
  },
  poison: {
    backgroundColor: '#a040a0',
  },
  ground: {
    backgroundColor: '#e0c068',
  },
  flying: {
    backgroundColor: '#a890f0',
  },
  psychic: {
    backgroundColor: '#f85888',
  },
  bug: {
    backgroundColor: '#a8b820',
  },
  rock: {
    backgroundColor: '#b8a038',
  },
  ghost: {
    backgroundColor: '#705898',
  },
  dragon: {
    backgroundColor: '#7038f8',
  },
  dark: {
    backgroundColor: '#705848',
  },
  steel: {
    backgroundColor: '#b8b8d0',
  },
  fairy: {
    backgroundColor: '#e898e8',
  },
});

export default Pokemon;

위의 코드에서 먼저 이름에 잘못된 값이 있는지 확인했습니다. 그럴 경우 렌더링 할 항목이 없으므로 단순히 null을 반환합니다.


또한 두 가지 새로운 내장 React Native 구성 요소를 사용하고 있습니다.


  • Image: 인터넷 또는 파일 시스템에서 이미지를 표시하는 데 사용됩니다.
  • FlatList: 목록 표시에 사용

앞서 살펴본 것처럼 Pokémon 데이터를이 구성 요소의 소품으로 전달합니다. 객체에서 개별 속성을 추출하는 것과 같은 방식으로 이러한 소품을 추출 할 수 있습니다.


const Pokemon = ({ name, pic, types, desc }) => {
    // ..
};

이미지 구성 요소에는 소스가 전달되어야 합니다. 소스는 파일 시스템의 이미지이거나 이 경우 인터넷의 이미지 일 수 있습니다. 전자는 require ()를 사용하여 이미지를 포함해야 하는 반면 후자는 전달하는 객체의 uri 속성 값으로 사용할 이미지 URL을 요구합니다.


resizeMode를 사용하면 컨테이너에 따라 이미지 크기가 조정되는 방식을 제어 할 수 있습니다. 포함을 사용했습니다. 즉, 이미지 크기를 조정하여 이미지 비율을 유지하면서 컨테이너에 맞도록 합니다. 컨테이너는 이미지 구성 요소 자체입니다. 너비와 높이를 100으로 설정 했으므로 이미지 크기가 해당 크기로 조정됩니다. 원본 이미지의 너비가 높이보다 넓은 경우 너비 100이 사용되고 가로 세로 비율을 유지하기 위해 높이가 조정됩니다. 원본 이미지 크기가 더 작으면 원래 크기 만 유지됩니다.


<Image source={{ uri: pic }} style={styles.image} resizeMode={"contain"} />

다음은 FlatList 구성 요소입니다. 항목 목록을 렌더링 하는 데 사용됩니다. 이 경우에는 포켓몬의 유형을 렌더링 하는 데 사용합니다. 이를 위해서는 렌더링 할 항목을 포함하는 배열 인 데이터와 목록의 각 항목을 렌더링 하는 기능인 renderItem이 필요합니다. 현재 반복의 항목은 기능 구성 요소에서 소품에 액세스하는 것과 동일한 방식으로 액세스 할 수 있습니다.


<FlatList
  columnWrapperStyle={styles.types}
  data={types}
  numColumns={2}
  keyExtractor={(item) => item.id.toString()}
  renderItem={({ item }) => (
    <View style={[styles[item.name], styles.type]}>
      <Text style={styles.typeText}>{item.name}</Text>
    </View>
  )}
/>

위의 코드에서 다음 소품도 제공했습니다.


  • columnWrapperStyle : 각 열의 스타일을 지정하는 데 사용됩니다. 이 경우 각 목록 항목을 인라인으로 렌더링하려고 하므로 flexDirection : 'row'를 지정했습니다.
  • numColumns : 목록의 각 행에 대해 렌더링 할 최대 열 수입니다. 이 경우 포켓몬은 최대 두 가지 유형 만 가질 수 있으므로 2를 지정했습니다.
  • keyExtractor : 각 항목의 키를 추출하는 데 사용할 함수입니다. 각 목록 항목의 가장 바깥 쪽 구성 요소에 키 소품을 전달하면 실제로 이 항목을 생략 할 수 있습니다.

이제 장치 또는 에뮬레이터에서 앱을 테스트 할 수 있습니다.


yarn start

터미널에서 Android 에뮬레이터에서 앱을 실행하려면 a를 누르고 iOS 시뮬레이터에서 실행하려면 i를 누릅니다.


Pokémon의 이름은 대문자로 시작해야 합니다. 예를 들어, "pikachu"가 아니라 "Pikachu"입니다.


결론 및 다음 단계 


그게 다야! 이 자습서에서는 Expo를 사용하여 React Native 개발 환경을 설정하는 방법을 배웠습니다. 또한 첫 번째 React Native 앱을 만드는 방법도 배웠습니다.


자세한 내용은 다음 리소스를 확인하십시오.


또한 이 GitHub 저장소에서 이 가이드에 사용 된 소스 코드를 찾을 수 있습니다.