React Navigation

joker·2020년 5월 13일
0

ReactNative

목록 보기
1/1
post-thumbnail

출처 : https://reactnavigation.org/docs

React로 개발하고 React native의 webView를 이용하여 Mobile App을 개발하여 배포하였습니다.
그러고 나니 React native code만으로 App을 만들어서 배포하고 싶다는 생각이 들어서 찾아보다가
React Navigation이 기본 개념인 것 같아서 해당 내용을 정리해 놓으려고 합니다.

각 챕터는 모두 맨아래의 '코드 및 예제 화면 확인하기'를 통해 모든 코드 및 실제 동작 화면을 확인 할 수 있습니다.

Expo를 이용한 설치

npm install -g expo-cli

expo init AwesomeProject
cd AwesomeProject
npm start # you can also use: expo start

Getting started

React navigation 설치

npm install @react-navigation/native

Installing dependencies into an Expo managed project

expo install react-native-gesture-handler react-native-reanimated react-native-screens react-native-safe-area-context @react-native-community/masked-view

Installing the stack navigator library

npm install @react-navigation/stack

Hello React navigation

항상 시작은 Hello World죠..

// In App.js in a new project

import * as React from 'react';
import { View, Text } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';

function HomeScreen() {
  return (
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
      <Text>Home Screen</Text>
    </View>
  );
}

function DetailsScreen() {
  return (
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
      <Text>Details Screen</Text>
    </View>
  );
}

const Stack = createStackNavigator();

function App() {
  return (
    <NavigationContainer>
      <Stack.Navigator initialRouteName="Home">
        <Stack.Screen name="Home" component={HomeScreen} options={{ title: 'Overview' }} />
        <Stack.Screen name="Details" component={DetailsScreen} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

export default App;

  • 네비게이터 구성
    Home 과 Detail 두가지의 탭중에서 initalRouteName을 Home으로 설정하여 Home이 최초로 랜더링 되게 설정 할 수 있다.
<Stack.Navigator initialRouteName="Home">
  • 옵션지정
    ScreenOptions props를 네비게이터에 전달 할 수 있습니다.
<Stack.Screen name="Home" component={HomeScreen} options={{ title: 'Overview' }} />
<Stack.Screen
  name="Home"
  component={HomeScreen}
  options={{ title: 'Overview' }}
/>

코드 및 예제 화면 확인하기

Summary(요약)

  • React native에는 web browser처럼 탐색을 위한 API가 내정되어 있지 않습니다.
    화면 간 전환을 위해서는 React navigation을 사용합니다. (a 태그가 없음)
  • Stack.Screen의 Component(구성요소)인 name prop는 해당 route의 이름을 의미하며 component prop는 redering할 component를 지정하는 prop를 가져옵니다. name과 component는 2가지 필수 prop 입니다

Moving between screens

화면 간 이동하는 방법에 대해 알아보겠습니다

위에서 Home과 Detail 탭을 나누었지만 경로를 연결하지 않았습니다.
만일 웹 브라우저였다면 아래와 같이 작성이 되겠죠

<a href="details.html">Go to Details</a>

이것을 쓰는 또 다른 방법은 다음과 같습니다.

<a
  onClick={() => {
    window.location.href = 'details.html';
  }}
>
  Go to Details
</a>

이것처럼 React navigation에서 화면 간 이동을 하는 방법에 대해 알아 보겠습니다.

function HomeScreen({ navigation }) {
  return (
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
      <Text>Home Screen</Text>
      <Button
        title="Go to Details"
        onPress={() => navigation.navigate('Details')}
      />
    </View>
  );
}
  • HomeScreen argument안에 추가된 { navigation }
    navigation props는 stack navigator안에 모든 screen component에 전달됩니다.
    자세한 내용은 "The navigation prop in depth" 에서 나중에 확인 할 수 있습니다.

Stack.Screen에 name=Details로 정한 곳으로 이동시키려는 것입니다.

 onPress={() => navigation.navigate('Details')}

코드 및 예제화면 확인하기

function DetailsScreen({ navigation }) {
  return (
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
      <Text>Details Screen</Text>
      <Button
        title="Go to Details... again"
        onPress={() => navigation.push('Details')}
      />
      <Button title="Go to Home" onPress={() => navigation.navigate('Home')} />
      <Button title="Go back" onPress={() => navigation.goBack()} />
      <Button
        title="Go back to first screen in stack"
        onPress={() => navigation.popToTop()}
      />
    </View>
  );
}

위의 예시처럼 응용도 가능합니다

  1. navigate를 이용하여 Home으로 이동
  2. goBack을 이용하여 뒤로가기로 이동
  3. popToTop() 함수를 이용하여 Stack의 첫 번째 화면으로 이동

코드 및 예제화면 확인하기

요약

  • navigation.navigate('RouteName') 스택 경로에 스택 경로 탐색기가 없으면 새 경로를 푸시합니다. 그렇지 않으면 해당 화면으로 이동합니다.
    우리는 원하는 navigation.push('RouteName')만큼 전화를 걸 수 있으며 계속해서 노선을 추진할 것입니다.
  • 헤더 표시 줄에 자동으로 뒤로 버튼이 표시되지만을 호출하여 프로그래밍 방식으로 돌아갈 수 있습니다 navigation.goBack(). Android에서는 하드웨어 뒤로 버튼이 예상대로 작동합니다.
    을 사용하여 스택의 기존 화면으로 돌아가고을 사용하여 스택 navigation.navigate('RouteName')의 첫 번째 화면으로 돌아갈 수 있습니다 navigation.popToTop().
    navigation소품 모든 화면 구성 요소 (경로 구성의 화면과 같이 정의 경로로 탐색 반응에 의해 렌더링 구성 요소)을 사용할 수 있습니다

Passing parameters to routes

routes에 parameters(매개 변수)를 전달하는 방법에 대해 알아보겠습니다.

routes를 사용할 때 routes에 data를 전달하는 방법은 크게 2가지가 있습니다

  1. 두번째 파라미터에 데이터를 전달
    navigation.navigate function: navigation.navigate('RouteName', { / params go here / })

  2. Read the params in your screen component: route.params.

function HomeScreen({ navigation }) {
  return (
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
      <Text>Home Screen</Text>
      <Button
        title="Go to Details"
        onPress={() => {
          /* 1. Navigate to the Details route with params */
          navigation.navigate('Details', {
            itemId: 86,
            otherParam: 'anything you want here',
          });
        }}
      />
    </View>
  );
}

function DetailsScreen({ route, navigation }) {
  /* 2. Get the param */
  const { itemId } = route.params;
  const  otherParam  = route.params.otherParam;
  return (
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
      <Text>Details Screen</Text>
      <Text>itemId: {JSON.stringify(itemId)}</Text>
      <Text>otherParam: {JSON.stringify(otherParam)}</Text>
      <Button
        title="Go to Details... again"
        onPress={() =>
          navigation.push('Details', {
            itemId: Math.floor(Math.random() * 100),
          })
        }
      />
      <Button title="Go to Home" onPress={() => navigation.navigate('Home')} />
      <Button title="Go back" onPress={() => navigation.goBack()} />
    </View>
  );
}
  1. navigation.navigate의 두번째 파라미터로 해당 data를 첫번째 파라미터 route인 details로 보낸다

  2. parameter를 가져올 때 선언 방법은 2가지 입니다.

  • const { itemId } = route.params; 처럼 가져오면서 선언과 대입을 하는 경우
  • cosnt otherParam = route.params.otherParam; 가져온 다음에 선언과 대입을 하는 경우
  1. JSON.stringify()는 JavaScript 값이나 객체를 JSON 표기법으로 변환 시킵니다.

Updating params

이런식으로 기본 값을 설정해 놓을 수도 있습니다.

<Stack.Screen
  name="Details"
  component={DetailsScreen}
  initialParams={{ itemId: 42 }}
/>

코드 및 예제화면 확인하기

이전 화면으로 params를 전달하는 방법에 대해 알아 보겠습니다.

예를들어 게시물 만들기 버튼이 있는 화면이 있을때, 해당 버튼을 클릭하면 새로운 화면으로 전환되면서 그곳에서 게시문을 만듭니다. 이후 작성한 게시물의 데이터를 다시 이전으로 전달 하려고 할때 사용합니다.

같은 파일 안에 있는 함수들이나 코드가 길어져 나누어서 보도록 하겠습니다

function HomeScreen({ navigation, route }) {
  React.useEffect(() => {
    if (route.params?.post) {
      // Post updated, do something with `route.params.post`
      // For example, send the post to the server
    }
  }, [route.params?.post]);

  return (
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
      <Button
        title="Create post"
        onPress={() => navigation.navigate('CreatePost')}
      />
      <Text style={{ margin: 10 }}>Post: {route.params?.post}</Text>
    </View>
  );
}

function CreatePostScreen({ navigation, route }) {
  const [postText, setPostText] = React.useState('');

  return (
    <>
      <TextInput
        multiline
        placeholder="What's on your mind?"
        style={{ height: 200, padding: 10, backgroundColor: 'white' }}
        value={postText}
        onChangeText={setPostText}
      />
      <Button
        title="Done"
        onPress={() => {
          // Pass params back to home screen
          navigation.navigate('Home', { post: postText });
        }}
      />
    </>
  );
}

useState와 useEffect에 대해 잘모르시는 분들은 클릭

코드 및 예제화면 확인하기

요약

  1. navigate그리고 push당신은 당신이로 이동하는 경로에 매개 변수를 전달할 수 있도록 선택적인 두 번째 인수에 동의합니다. 예를 들면 다음과 같습니다 navigation.navigate('RouteName', {paramName: 'value'})..
  2. 당신은 route.params화면 내부를 통해 매개 변수를 읽을 수 있습니다
  3. 당신은 화면의 매개 변수를 업데이트 할 수 있습니다 navigation.setParams
  4. 초기 매개 변수는 initialParams소품을 통해 전달 될 수 있습니다 .Screen

Configuring the header bar

헤더 바를 구성하는 방법에 대해 알아보겠습니다.

function HomeScreen({ navigation }) {
  return (
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
      <Text>Home Screen</Text>
      <Button
        title="Go to Profile"
        onPress={() =>
          navigation.navigate('Profile', { name: 'Custom profile header' })
        }
      />
    </View>
  );
}

function ProfileScreen({ navigation }) {
  return (
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
      <Text>Profile screen</Text>
      <Button title="Go back" onPress={() => navigation.goBack()} />
    </View>
  );
}

const Stack = createStackNavigator();

function StackScreen() {
  return (
    <Stack.Navigator>
      <Stack.Screen
        name="Home"
        component={HomeScreen}
        options={{ title: 'My home' }}
      />
      <Stack.Screen
        name="Profile"
        component={ProfileScreen}
        options={({ route }) => ({ title: route.params.name })}
      />
    </Stack.Navigator>
  );
}


HomeScreen 함수에서버튼을 누르면 Profile 버튼으로 name값을 전송합니다.
App 함수에서 Stack.Screen의 options으로 title에 전달받은 name값을 표시합니다.

코드 및 예제화면 확인하기

<Button
  title="Update the title"
  onPress={() => navigation.setOptions({ title: 'Updated!' })}
/>

header의 title을 업데이트 하고 싶을 경우에는 setOptions를 사용합니다.

function StackScreen() {
  return (
    <Stack.Navigator>
      <Stack.Screen
        name="Home"
        component={HomeScreen}
        options={{
          title: 'My home',
          headerStyle: {
            backgroundColor: '#f4511e',
          },
          headerTintColor: '#fff',
          headerTitleStyle: {
            fontWeight: 'bold',
          },
        }}
      />
    </Stack.Navigator>
  );
}

header style을 사용할때는 세 가지의 주요 특성이 있습니다.
headerStyle, headerTintColor, headeTitleStyle

  • headerStyle: View헤더를 감싸는 스타일 객체에 적용됩니다 . 설정하면 backgroundColor헤더의 색상이됩니다.
  • headerTintColor: 뒤로 단추와 제목은 모두이 속성을 색상으로 사용합니다. 아래 예에서는 색조 #fff버튼 을 흰색 ( )으로 설정 하여 뒤로 버튼과 머리글 제목이 흰색이되도록합니다.
  • headerTitleStyle: 제목 의 fontFamily, fontWeight및 기타 Text스타일 속성 을 사용자 정의하려는 경우 이를 사용하여 제목을 지정할 수 있습니다.

코드 및 예제화면 확인하기

Summary

  • options화면 구성 요소 의 소품 내부에서 헤더를 사용자 정의 할 수 있습니다 . API 참조 서 의 전체 옵션 목록을 읽으 십시오 . 이곳을 클릭
  • options소품는 객체 나 함수가 될 수 있습니다. 함수 인 경우 navigation및 routeprop이 포함 된 객체가 제공됩니다 .
  • screenOptions스택 탐색기 구성을 공유 할 때 공유 를 지정할 수도 있습니다. 소품이 해당 구성보다 우선합니다.
function StackScreen() {
  return (
    <Stack.Navigator
      screenOptions={{
        headerStyle: {
          backgroundColor: '#f4511e',
        },
        headerTintColor: '#fff',
        headerTitleStyle: {
          fontWeight: 'bold',
        },
      }}
    >
      <Stack.Screen
        name="Home"
        component={HomeScreen}
        options={{ title: 'My home' }}
      />
    </Stack.Navigator>
  );
}

보통은 모든 화면에서 비슷한 방식으로 헤더를 구성하는게 일반적입니다.
이 경우 따로 모든 Stack.Screen에 options을 줄 필요 없이 screenOptions을 사용합니다.

function LogoTitle() {
  return (
    <Image
      style={{ width: 50, height: 50 }}
      source={require('@expo/snack-static/react-native-logo.png')}
    />
  );
}

function StackScreen() {
  return (
    <Stack.Navigator>
      <Stack.Screen
        name="Home"
        component={HomeScreen}
        options={{ headerTitle: props => <LogoTitle {...props} /> }}
      />
    </Stack.Navigator>
  );
}

title 명보다 스타일을 수정하거나 이미지를 삽입하게 되는 경우가 존재 할 수 있습니다.
커스텀 컴포넌트를 삽일할때는 위와같이 사용합니다.

코드 및 예제 화면 확인하기

Header buttons

header를 customize 하는 방법을 알았으니 button을 적용해 봅시다.

function StackScreen() {
  return (
    <Stack.Navigator>
      <Stack.Screen
        name="Home"
        component={HomeScreen}
        options={{
          headerTitle: props => <LogoTitle {...props}![](https://media.vlpt.us/images/joker/post/c1d4aa11-698c-4888-8c4c-2c883c9bb371/react-navigation-cover.png) />,
          headerRight: () => (
            <Button
              onPress={() => alert('This is a button!')}
              title="Info"
              color="#fff"
            />
          ),
        }}
      />
    </Stack.Navigator>
  );
}

headerRight에 Button을 생성하였습니다 이 버튼을 클릭 시 This is a button 이라는 alert이 출력됩니다.

profile
개발자입니다.

0개의 댓글