JiSoo's Devlog

[React Native] React Native 내비게이션 본문

App/React Native

[React Native] React Native 내비게이션

지숭숭숭 2024. 5. 8. 12:27

내비게이션이란 여러 화면 간 이동할 수 있도록 해주는 것

모바일 앱에서는 URL 대신 버튼을 눌러 한 화면에서 다른 화면으로 이동하거나 이전 화면으로 돌아가는 방식

 

카테고리들을 출력하기 위해 FlatList 사용

항목이 얼마나 많이 포함될지 미리 알 수 없는 동적 목록일 때 FlatList 사용할 수 있다

요소를 느리게 렌더링 하기 위해서도 사용 가능

고정된 목록에서는 필요 X

<FlatList data={CATEGORIES} keyExtractor={(item) => item.id} />

키가 있어야 하는데 키 프로퍼티가 없다면 keyExtractor 함수 설정 필요

keyExtractor 함수는 자동으로 item을 매개변수로 받고 FlatList에 의해 렌더링 되는 개별 항목의 키로 사용할 수 있는 값을 반환해야 한다

renderItem 프로퍼티로 각 항목에 실행될 함수를 정의해 항목을 렌더링 하는 방법을 결정할 수 있게 해야 한다

numColumns 프로퍼티를 추가해 숫자를 지정하면 열을 강제로 쉽게 추가할 수 있다

 

flex를 1로 설정하면 부모 컨테이너 안에서 사용 가능한 모든 공간 확보 가능!

 

React Navigation

Expo와 React Native 앱에 라우팅 및 내비게이션을 추가하기 위해 만들어진 패키지

npm install @react-navigation/native

↑ 패키지 설치

expo install react-native-screens react-native-safe-area-context

↑ 의존성 설치

React Navigation은 컴포넌트 기반 라이브러리이므로 내비게이션 구성을 설정할 수 있는 다양한 컴포넌트를 제공한다

NavigationContainer 컴포넌트로 내비게이션이 적용되어야 할 앱 내의 모든 컴포넌트를 감싸야하는데 보통 앱 전체를 감싼다

StatusBar는 상태 표시줄의 스타일링만 조정하는 유틸리티 컴포넌트이므로 감쌀 필요 없다

React Navigation을 사용할 때는 NavigationContainer를 만들고 지원되는 내비게이터 중 하나를 사용해야 한다

내비게이터는 각기 다른 내비게이션 동작을 구현한다

드로어 내비게이터는 사이드 바 제공

탭 내비게이터는 사용자 간에 전환 가능한 탭을 제공하는데 여러 종류가 있다

 

스택 내비게이터 패키지 설치 ↓

expo install @react-navigation/native-stack

패키지에서 createNativeStackNavigator를 임포트 해야 한다

App 컴포넌트 외부에서 이 함수를 호출해 스택을 만들어야 한다

이 스택은 두 개의 프로퍼티를 갖는 객체이며 각 프로퍼티는 컴포넌트의 기능을 가진 객체를 포함한다

const Stack = createNativeStackNavigator();

export default function App() {
  return (
    <>
      <StatusBar style="light" />
      <NavigationContainer>
        <Stack.Navigator>
          <Stack.Screen name="MealsCategories" component={CategoriesScreen} />
        </Stack.Navigator>
      </NavigationContainer>
    </>
  );
}

모든 화면에 이름을 지정할 수 있는데 이는 고유한 식별자로써 화면 간 이동할 때 중요한 역할을 한다

해당 화면을 제공하는 데 사용될 컴포넌트를 이름으로만 설정해 준다

 

<Stack.Navigator>를 통해 Navigator를 설정하고 <Stack.Screen>을 통해 화면을 등록할 때는 앱이 시작할 때 어떤 화면이 기본으로 표시될지를 설정할 수 있다

아무런 설정 없이는 가장 위에 있는 화면인 <Stack.Navigator> 내의 첫 번째 자식 요소가 초기 화면이 된다

<Stack.Screen> 순서를 변경함으로써 초기 화면을 변경할 수 있다

내비게이터 컴포넌트(<Stack.Navigator>)에 설정할 수 있는 initialRouteName 프로퍼티 사용도 가능

 

사용되는 컴포넌트들은 구조 분해를 통해 pull 할 수도 있는 프로퍼티인 navigation을 받는다

function CategoriesScreen({ navigation })

이 프로퍼티는 화면 사이를 이동하게 하는 메서드를 포함하는 객체가 된다

navigate 메서드는 React Navigation이 제공하며 navigation 객체를 프로퍼티로 받는다

function presssHandler() {
    navigation.navigate("MealsOverview");
  }

이동하고 싶은 페이지 이름을 문자열 형식으로 navigate에 인수로 전달하면 화면 이동 가능

 

내비게이터에는 네이티브 스택도 있고 스택도 있다

두 내비게이터는 보통 같은 방식으로 작동하며 같은 내비게이션 기능을 제공한다

스택 기반 내비게이션은 화면 위에 다른 페이지를 푸시하고 이전 화면으로 돌아갈 수 있다

네이티브 스택은 애니메이션과 화면에 대해 네이티브 플랫폼 요소를 사용하기 때문에 네이티브 동작을 흉내 내는 스택보다 성능이 더 높을 수 있다

그래서 보통 네이티브 스택을 선호!

일반적으로는 Screen으로 설정된 컴포넌트를 통해 navigate를 얻는데 내비게이션 동작을 초기화하는 또 다른 컴포넌트가 있다면 그런 컴포넌트 내에서 내비게이션 하는 다른 함수를 정의해 전달도 가능

 

Screen으로 등록되었는지와 관계없이 모든 컴포넌트 함수에서 useNavigation 훅을 실행할 수 있고 navigation 객체를 제공한다

import { useNavigation } from "@react-navigation/native";

 

 

화면 사이에 데이터를 전달하기 위해서는 navigation 프로퍼티의 navigate 메서드 사용

navigate 메서드는 이동하고자 하는 화면의 이름을 필수 매개변수의 값으로 가진다

선택사항으로 두 번째 매개변수 값에 객체 전달도 가능한데 이 객체를 통해 params를 정의할 수 있다

내비게이션을 통해 전달된 매개변수 추출을 위해 대상 화면에서 navigation 프로퍼티 입력 후 객체 구조 분해를 통해 해당 프로퍼티 객체를 추출할 수 있다

React Navigation에서 Screen으로 등록된 컴포넌트라면 navigation 프로퍼티와 더불어 route 프로퍼티도 받는다

route 프로퍼티에는 params 프로퍼티가 있다

route 프로퍼티 대신 useRoute 훅을 사용해도 된다

프로퍼티에서 받았던 것과 같은 route 객체를 받고 params를 받을 수 있다

Screen으로 등록되지 않은 중첩 컴포넌트에서 현재 로딩된 정보에 접근할 경우 useRoute 훅을 사용한다

 

웹으로부터 이미지를 로딩하려면 source를 설정하면 되는데 값을 객체로 설정 후 객체에 uri 키를 추가하면 된다

uri는 이미지에 대한 URL을 의미한다

웹 이미지를 사용할 때는 가로세로 길이를 정의하는 스타일을 추가해야 한다

 

객체 내의 모든 프로퍼티를 컴포넌트의 프로퍼티로 배분하기

 function renderMealItem(itemData) {
    const item = itemData.item;
    const mealItemProps = {
      title: item.title,
      imageUrl: item.imageUrl,
      affordability: item.affordability,
      complexity: item.complexity,
      duration: item.duration,
    };
    return <MealItem {...mealItemProps} />;

 

기본 화면 옵션을 설정하려면 각각의 개별 화면에 옵션을 설정하는 대신 모든 화면에 적용할 옵션을 선택해 내비게이터에 추가하면 된다

<Stack.Navigator
  screenOptions={{
    headerStyle: { backgroundColor: "#351401" },
    headerTintColor: "white",
    contentStyle: { backgroundColor: "#3F2F25" },
  }}
>

 

옵션을 동적으로 설정하는 방법

- 화면 구성 컴포넌트에서 options 프로퍼티 사용

객체를 전달하는 대신 함수 전달도 가능

<Stack.Screen
  name="MealsOverview"
  component={MealsOverviewScreen}
  options={({ route, navigation }) => {
      const catId = route.params.categoryId;
      return {
        title: catId,
      };
    }}
  />

함수는 화면이 활성화될 때마다 실행되고 options 객체를 반환한다

- 컴포넌트 내부에 옵션 설정

화면 컴포넌트는 route와 navigation 프로퍼티를 자동으로 얻게 된다

navigation 프로퍼티는 navigate 메서드 외에도 setOptions 메서드를 가지는데 이 메서드는 객체를 취하고 옵션으로 설정된다

useLayoutEffect(() => {
    const categoryTitle = CATEGORIES.find(
      (category) => category.id === catId
    ).title;
    navigation.setOptions({
      title: categoryTitle,
    });
  }, [catId, navigation]);

useLayoutEffect 훅은 애니메이션이 실행되는 동안 부수 효과를 설정하거나 실행할 때 사용 가능

컴포넌트가 렌더링 되기 전에 부수 효과를 실행하는 것

 

헤더에 버튼 만들기

function headerButtonPressHandler() {
    console.log("Pressed!");
  }
  useLayoutEffect(() => {
    navigation.setOptions({
      headerRight: () => {
        return (
          <IconButton
            icon="star"
            color="white"
            onPress={headerButtonPressHandler}
          />
        );
      },
    });
  }, [navigation, headerButtonPressHandler]);

setOptionsheaderRight 혹은 headerLeft로 헤더에 추가

 

드로어 내비게이터

앱의 측면 드로어를 추가하는 내비게이터

npm install @react-navigation/drawer
expo install react-native-gesture-handler react-native-reanimated
return (
    <NavigationContainer>
      <Drawer.Navigator>
        <Drawer.Screen name="Welcome" component={WelcomeScreen} />
        <Drawer.Screen name="User" component={UserScreen} />
      </Drawer.Navigator>
    </NavigationContainer>
  );

 

드로어 내비게이터에도 options 프로퍼티로 객체를 옵션으로 전송해 다양한 설정 가능

navigation 프로퍼티에는 스택 내비게이션에는 없던 toggleDrawer 메서드가 있다

이 메서드는 드로어를 전환한다 (닫혔을 때는 열리고 열렸을 때는 닫힌다)

function openDrawerHandler() {
    navigation.toggleDrawer();
  }

 

하단 탭 내비게이터

npm install @react-navigation/bottom-tabs

커스터마이징한 탭을 렌더링 할 수도 있다

라벨 표시 여부 등 조정 가능

 

 

728x90