얼렁뚱땅

[React Native] Stack Navigation 사용하기 본문

React Native

[React Native] Stack Navigation 사용하기

당당익명 2021. 8. 18. 20:06

Stack Navigation 이란?

현재 화면 위에 다른 화면을 쌓으면서 화면을 이동하는 것. push와 pop을 이용하기 때문에 stack이다.

 

Stack Navigation 라이브러리 설치

npm i @react-navigation/stack

 


파일, 폴더 구성

screen 폴더

  • Mainscreen.js
  • Result.js

navigations 폴더

  • MainscreenStack.js
  • MypageStack.js (추후 생성 예정)

기본 구조는 tab이나 drawer와 비슷하다.

 

src 밖 App.js -> src/App.js -> navigations/index.js -> MainTab.js -> MainscreenStack.js -> Mainscreen.js, Result.js 페이지 가져오기!

 

src 밖 App.js

import App from './src/App';

export default App;

모든 코드를 src 폴더 내에서 관리하는 것이 편해서 이렇게 했다.

 

src/App.js

import React from 'react';
import Navigation from './navigations';

export default function App() {
  return <Navigation />;
}

이상하게 <View> component 안에 <Navigation>을 두면 화면이 아무것도 안나타난다. 그래서 일단은 임시로 이렇게 두었다. 나중에 <ThemeProvider>를 사용할 예정. <Navigation> 컴포넌트 가져오기.

 

navigations/index.js

import React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import MainTab from './MainTab';

const Navigation = () => {
  return (
    <NavigationContainer>
      <MainTab />
    </NavigationContainer>
  );
};

export default Navigation;

반드시 <NavigationContainer>로 감싸주어야 한다. <MainTab> 컴포넌트 가져오기.

 

navigations/MainTab.js

import React from 'react';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import MainscreenStack from './MainscreenStack';
import Mypage from '../screens/Mypage';
import Instagram from '../screens/Instagram';

const Tab = createBottomTabNavigator();

const MainTab = () => {
  return (
    <Tab.Navigator>
      <Tab.Screen name="MainscreenStack" component={MainscreenStack} />
      <Tab.Screen name="Mypage" component={Mypage} />
      <Tab.Screen name="Instagram" component={Instagram} />
    </Tab.Navigator>
  );
};

export default MainTab;

3개의 tab으로 구성. 이건 기본 틀만 보여주기 위한 코드이고, tab, drawer navigation이 모두 완성된 코드는 아래 참고.

https://dev-sailor.tistory.com/27

 

[React Native] Tab Navigation 사용하기

Tab Navigation을 위한 라이브러리 설치 npm i @react-navigation/bottom-tabs 파일, 폴더 구성 (기본 뼈대 구성) src 밖 App.js -> src 안 App.js -> navigations 폴더의 index.js -> MainTab.js -> Mainscreen...

dev-sailor.tistory.com

 


stack navigation 만들기

MainscreenStack.js

import React from 'react';
import { createStackNavigator } from '@react-navigation/stack';
import Mainscreen from '../screens/Mainscreen';
import Result from '../screens/Result';

const Stack = createStackNavigator();

const MainscreenStack = () => {
  return (
    <Stack.Navigator>
      <Stack.Screen name="Mainscreen" component={Mainscreen} />
      <Stack.Screen name="Result" component={Result} />
    </Stack.Navigator>
  );
};

export default MainscreenStack;
  • createStackNavigator 함수를 이용해서 스택 네비게이션 생성
  • Navigator 컴포넌트 안에 Screen 컴포넌트를 자식 컴포넌트로 작성
  • Screen 컴포넌트 안에 Mainscreen 컴포넌트와 Result 컴포넌트로 지정

Mainscreen이 가장 먼저 나오고 버튼을 누르면 result 페이지로 이동하도록 설정할 것이다.

 

Mainscreen.js

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

export default function Mainscreen({ navigation }) {
  return (
    <View style={styles.container}>
      <Text style={styles.text}>MainScreen Page</Text>
      <Button
        title="go to Result page"
        onPress={() => navigation.navigate('Result')}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
  text: {
    fontSize: 30,
  },
});

Screen 컴포넌트의 component로 지정된 컴포넌트는 화면으로 이용되고 navigation이 props로 전달된다

navigation에는 다양한 기능이 있는데 그중 navigate 함수는 원하는 화면으로 이동하는 데 사용된다.

 

Mainscreen 화면에서 props로 전달되는 navigation을 사용해서 버튼을 클릭하면 Result 화면으로 이동하도록 만든 것이다. 단, 전달되는 화면의 이름은 screen 컴포넌트의 name 값 중 하나를 입력해야 한다.

 

기본 틀만 만들면 위와 같은 화면이 나온다. header가 두번 나오는 문제가 있다.


Header 숨기기 

사용할 수 있는 설정이 2가지가 있다.

  1. headerMode
  2. headerShown

headerMode

Navigator 컴포넌트의 속성으로 헤더를 렌더링하는 방법 설정

  • float : 헤더가 상단에 유지되면 하나의 헤더 사용. iOS 동작 방식
  • screen : 각 화면마다 헤더를 가지며 화면 변경과 함꼐 나타나거나 사라짐. Andriod 동작 방식
  • none : 헤더가 렌더링 되지 않음

hearderShown

화면 옵션

Navigator 컴포넌트의 screenOptions에서 설정하면 전체 화면의 헤더가 보이지 않고

Screen 컴포넌트의 options에서 설정하면 그 화면에서만 헤더가 보이지 않는다.

 

나는 headerShown : false 를 Mainscreen 페이지에서 사용했다.

 

MainTab.js

<Tab.Screen
        name="Mainscreen"
        component={MainscreenStack}
        options={{
          headerShown: false,
          tabBarIcon: (props) =>
            TabIcon({
              ...props,
              name: props.focused ? 'home-variant' : 'home-variant-outline',
            }),
        }}
      />

헤더 중복 문제 해결

 

Header 가운데 정렬

헤더를 가운데 정렬 시키고 싶다.

 

headerTitleAlign 속성을 이용한다.

 

headerTitleAlign에서는 left와 center 두 가지가 값 중 하나만 설정할 수 있다. iOS는 center로, 안드로이드는 left가 기본값으로 설정되어 있다.

 

MainscreenStack.js

<Stack.Navigator screenOptions={{ headerTitleAlign: 'center' }}>
      <Stack.Screen name="Mainscreen" component={Mainscreen} />
      <Stack.Screen name="Result" component={Result} />
    </Stack.Navigator>


이동하는 화면에 정보 전달하기

navigate 함수를 이용할 때 두 번째 파라미터에 객체를 전달해서 이동하는 화면에 필요한 정보를 함께 전달하는 기능이 있다. 

이번에는 Mypage에서 코드를 작성해보고자 한다.

 

먼저 화면에서 사용할 임시 목록을 만들기

Mypage.js

const items = [
  { id: 1, name: 'first image' },
  { id: 2, name: 'second image' },
  { id: 3, name: 'third image' },
];

 

그리고 항목 수 만큼 버튼 생성하기

{items.map((item) => (
        <Button
          key={item.id}
          title={item.name}
          onPress={() => _onPress(item)}
        />
      ))}

 

버튼을 눌렀을 때 해당 항목의 정보와 함께 화면 이동하기

navigate 함수를 이용 시 두번째 파라미터에 객체를 전달

const _onPress = (item) => {
    navigation.navigate('Image', { id: item.id, name: item.name });
  };

 

전달된 내용은 컴포넌트의 props로 전달되는 route의 params를 통해 확인 가능

Image.js

export default function Image({ route }) {
  return (
    <View style={styles.container}>
      <Text style={styles.text}>Image Page</Text>
      <Text>ID: {route.params.id}</Text>
      <Text>Name: {route.params.name}</Text>
    </View>
  );
}