스파르타코딩클럽 내일배움캠프 TIL48

한재창·2023년 1월 5일
0

RactNavigation

  • 리액트 네비게이션에서 지원하는 네비게이션의 종류는 스택(stack) 네비게이션, 탭(tab) 네비게이션, 드로어(drawer) 네비게이션 세 종류이다. 이 포스트에서는 리액트 네비게이션5 버전을 기준으로 진행할 것이다.
  • 종류
    • NavigationContainer 컴포넌트
      • 네비게이션의 계층구조와 상태를 관리하는 컨테이너 역할을 하며, 모든 네비게이션 구성 요소를 감싼 최상위 컴포넌트이다.
    • Navigator 컴포넌트
      • 화면을 관리하는 중간 관리자 역할로 네비게이션을 구성하며, 여러 개의 Screen 컴포넌트를 자식 컴포넌트로 가진다.
    • Screen 컴포넌트
      • Screen 컴포넌트는 화면으로 사용되는 컴포넌트로 name과 component 속성을 지정해야 한다.

DarkMode

  • NavigationContainer theme props
    • "userInterfaceStyle": "automatic" 로 변경
    • NavigationContainer에 theme props를 적용한다.
    • 리액트 네이티브에서 제공하는 useColorScheme 훅을 사용하여 다크모드인지 아닌지 판별한다.
    • theme props를 다크모드라면 리액트 네이티브에서 제공하는 Theme인 DarkTheme 아니라면 DefaultTheme로 설정한다.
  • ThemeProvider
    • emotion 라이브러리에서 제공해주는 ThemeProvider 컴포넌트를 제일 외각에 씌워주면 theme을 제공해줄 수 있다.
    • 앞으로 styledComponents를 사용할 때 props.theme 으로 어디서든 자유롭게 접근할 수 있다.

연습 코드

// App.jsx

import {
  DarkTheme,
  DefaultTheme,
  NavigationContainer,
} from "@react-navigation/native";
import Root from "./navigation/Root";
import { useColorScheme } from "react-native";
import { ThemeProvider } from "@emotion/react";
import { darkTheme, lightTheme } from "./theme";

export default function App() {
  const isDark = useColorScheme() === "dark";
  return (
    <ThemeProvider theme={isDark ? darkTheme : lightTheme}>
      <NavigationContainer theme={isDark ? DarkTheme : DefaultTheme}>
        <Root />
      </NavigationContainer>
    </ThemeProvider>
  );
}
// StackNav.jsx

import { Text, TouchableOpacity } from "react-native";
import { createNativeStackNavigator } from "@react-navigation/native-stack";
// 네비게이터를 사용하기 위해서 NavigationContainer을 최상단 컴포넌트에서 감싸주어야 한다.
// install npm install @react-navigation/native
// install npx expo install react-native-screens react-native-safe-area-context
// install npm install @react-navigation/native-stack

const Stack = createNativeStackNavigator();

// 스크린 컴포넌트는 기본적으로 navigation이라는 props를 가지고 있다.
// navigation이라는 props에는 여러가지 메소드가 있는데 페이지 이동을 위해 navigate를 사용한다.
// route를 통해 params를 받을 수 있다.
const One = ({ route: { params }, navigation: { navigate } }) => {
  console.log(params); // {"id": 123}
  return (
    <TouchableOpacity onPress={() => navigate("two")}>
      <Text>One</Text>
    </TouchableOpacity>
  );
};

// setOptions는 객체를 인자로 받는다.
// 밑의 코드는 헤더부분의 타이틀이 바뀌게 된다.
const Two = ({ navigation: { navigate, setOptions } }) => {
  return (
    <>
      <TouchableOpacity onPress={() => navigate("three")}>
        <Text>Two</Text>
      </TouchableOpacity>
      <TouchableOpacity
        onPress={() =>
          setOptions({
            title: "변경된 제목!",
          })
        }
      >
        <Text>Set Options</Text>
      </TouchableOpacity>
    </>
  );
};

// goBack 메서드는 뒤로가기 기능
// reset 메서드는 unmount 기능을 가지고 있으며 네비게이션 스테이트 자체를 초기화 시켜준다.
// reset은 객체를 인자로 받고 index, routes가 있다.
// index : 0이면 1개의 화면, 1이면 2개 화면이고 마지막 값에서 시작하며 뒤로 가기 버튼을 눌렀을 때 마지막 값부터 차례대로 페이지가 나옴
// 만약에 "two" 화면으로 가면 뒤로 가기버튼이 사라지고 그 페이지가 처음 페이지처럼 보인다.
const Three = ({ navigation: { goBack, reset } }) => {
  return (
    <>
      <TouchableOpacity onPress={() => goBack()}>
        <Text>Three</Text>
      </TouchableOpacity>
      <TouchableOpacity
        onPress={() =>
          reset({
            index: 1,
            routes: [{ name: "three" }, { name: "one" }, { name: "two" }],
          })
        }
      >
        <Text>Reset Navigation</Text>
      </TouchableOpacity>
    </>
  );
};

// initialRouteName은 첫 화면을 지정해준다.
// screenOptions은 네비게이션에 옵션을 주는 props이며 객체를 인자로 받고, title, headerTintColor, headerShwon, headerBackTitle 등을 바꿀 수 있다.
export default function StackNav() {
  return (
    <Stack.Navigator
      initialRouteName="three"
      screenOptions={{
        headerTintColor: "red",
      }}
    >
      {/* 스크린 안에 있는 컴포넌트를 스크린 컴포넌트라고 부른다. */}
      {/* options은 스크린에 옵션을 주는 props이며 객체를 인자로 받는다. */}
      <Stack.Screen name="one" component={One} />
      <Stack.Screen name="two" component={Two} />
      <Stack.Screen
        options={{
          presentation: "modal",
        }}
        name="three"
        component={Three}
      />
    </Stack.Navigator>
  );
}
// BottomNav.jsx

import React from "react";
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";
import Movies from "../screen/MyMovies";
import My from "../screen/My";
import { MaterialIcons } from "@expo/vector-icons";
import { Foundation } from "@expo/vector-icons";
import { useColorScheme } from "react-native";
import { DARK_COLOR } from "../colors";

const Tab = createBottomTabNavigator();

// initialRouteName은 첫 화면을 지정해준다.
// screenOptions은 네비게이션에 옵션을 주는 props이며 객체를 인자로 받고, title, headerTintColor, headerShwon, headerBackTitle 등을 바꿀 수 있다.
// sceneContainerStyle은 스크린에 대한 스타일링을 할 수 있는 props이다.
export default function BottomTabNav() {
  const isDark = useColorScheme === "dark";
  // useColorScheme와 sceneContainerStyle를 활용해서 상위 컴포넌트에서 입혔던 색상을 덮어씌울 수 있다.
  return (
    <Tab.Navigator
      screenOptions={{
        tabBarLabelPosition: "beside-icon",
      }}
      sceneContainerStyle={{ backgroundColor: isDark ? DARK_COLOR : "white" }}
    >
      {/* options은 스크린에 옵션을 주는 props이며 객체를 인자로 받는다. */}
      {/* title: 헤더 제목을 바꿔줌, headerTitleAlign: 헤더 제목의 위치, tabBarLabel: 아래 탭의 내용을 바꿔줌 tabBarIcon: 아래 탭의 아이콘을 바꿔줌 */}
      <Tab.Screen
        options={{
          title: "영화",
          headerTitleAlign: "center",
          tabBarLabel: "Movies",
          tabBarIcon: ({ color, size }) => (
            <MaterialIcons name="local-movies" size={size} color={color} />
          ),
        }}
        name="Movies"
        component={Movies}
      />
      <Tab.Screen
        options={{
          title: "내가 작성한 댓글",
          tabBarLabel: "My",
          tabBarIcon: ({ color, size }) => (
            <Foundation name="social-myspace" size={size} color={color} />
          ),
        }}
        name="My"
        component={My}
      />
    </Tab.Navigator>
  );
}
// Root.jsx

import React from "react";
import { createNativeStackNavigator } from "@react-navigation/native-stack";
import { Text, TouchableOpacity } from "react-native";
import StackNav from "./StackNav";
import BottomTabNav from "./BottomTabNav";

const Stack = createNativeStackNavigator();

// 화면을 띄우면 헤더부분이 2개가 나온다.
// 1개는 여기에서의 헤더, 나머지는 BottomTabNav의 헤더
// 여기에서의 헤더를 screenOptions로 없앤다.
export default function Root() {
  return (
    <Stack.Navigator
      screenOptions={{
        headerShown: false,
      }}
    >
      <Stack.Screen name="BottomTabNav" component={BottomTabNav} />
      <Stack.Screen name="StackNav" component={StackNav} />
    </Stack.Navigator>
  );
}
// theme.js
// props.theme 으로 어디서든 자유롭게 접근하기 위해 이 파일에서 미리 설정해준다.

import { GREEN_COLOR, YELLOW_COLOR } from "./colors";

export const lightTheme = {
  title: GREEN_COLOR,
  upcomingText: "black",
};
export const darkTheme = {
  title: YELLOW_COLOR,
  upcomingText: "white",
};
profile
취준 개발자

0개의 댓글