[react native] React navigation 사용하기 (typescript)

potato·2024년 6월 3일

react native

목록 보기
1/2
post-thumbnail

react native 프로젝트에서 하단 탭 네비게이터스택 네비게이터를 동시에 사용하는 방법입니다.

react native 앱을 개발하면서 bottom-tabs-navigator와 stack-navigator가 둘 다 필요했는데,
각 tab에 있는 stack간 이동이 어려워서 tab navigator는 직접 제작하고 각 tab에 stack-navigator를 넣어주었습니다.
즉, bottom-tabs-navigator 라이브러리는 사용하지 않았습니다.

Stack Navigator 정의

먼저 이동할 페이지들을 stack navigator에 포함시켜 줍니다.

// DiaryNav.tsx

import { createNativeStackNavigator } from '@react-navigation/native-stack';

// 각 페이지 타입 지정
type DiaryStackParam = {
  DiaryList: undefined;
  EditDiary: undefined;
  WriteDiary: undefined;
  DiaryDetail: undefined;
};

// stack 네비게이터 생성
const DiaryStack = createNativeStackNavigator<DiaryStackParam>();

export const DiaryNav = () => {
  return (
    <DiaryStack.Navigator
      initialRouteName="DiaryList">
      // 해당 stack에서 이동할 페이지들
      <DiaryStack.Screen name="DiaryList" component={DiaryList} />
      <DiaryStack.Screen name="EditDiary" component={EditDiary} />
      <DiaryStack.Screen name="WriteDiary" component={WriteDiary} />
      <DiaryStack.Screen name="DiaryDetail" component={DiaryDetail} />
    </DiaryStack.Navigator>
  );
};
  • 원하는 페이지별로 그룹화 해 여러개의 stack-navigator를 만들어도 됩니다.
  • 저는 calendar, diary, user 이렇게 3개의 naviagator를 만들어주었습니다.

Bottom Tab Navigator 제작

  • 각 stack navigator를 포함할 Bottom Tab Naviagator를 만들어 줍니다.
  • 각 탭을 눌렀을 때 활성화 된 탭의 색을 변화시켜주며 이동시켰습니다.
// NavigationContext.tsx
// 활성화 된 탭의 상태를 전역으로 관리하는 context

import React, { createContext, useContext, useState } from 'react';

export type TabName = 'Calendar' | 'Diary' | 'Mypage';
interface NavigationContextType {
  currentTab: TabName;
  setCurrentTab: (tabName: TabName) => void;
}

const NavigationContext = createContext<NavigationContextType | undefined>(undefined);

export const NavigationProvider = ({ children }: { children: React.ReactNode }) => {
  const [currentTab, setCurrentTab] = useState<TabName>('Calendar');

  return <NavigationContext.Provider value={{ currentTab, setCurrentTab }}>{children}</NavigationContext.Provider>;
};

export const useNavigationState = () => {
  const context = useContext(NavigationContext);
  if (!context) {
    throw new Error('useNavigation must be used within a NavigationProvider');
  }
  return context;
};
// BottomTabNav.tsx

 import { useNavigation } from '@react-navigation/native';
 
 const BottomNav = () => {
  const navigation: any = useNavigation();
	
  // 활성화된 탭의 색 변화
  // context에서 따로 상태 관리
  const { currentTab, setCurrentTab } = useNavigationState();
  const getIconColor = (tabKey: string) => (currentTab === tabKey ? 'pink' : 'black');

  // 각 탭의 이름과 stack navigator, icon을 정의
  const tabs = [
    { key: 'Calendar', nav: 'CalendarNav', label: <Icon name="calendar" size={27} color={getIconColor('Calendar')} /> },
    { key: 'Diary', nav: 'DiaryNav', label: <Icon name="book" size={27} color={getIconColor('Diary')} /> },
    { key: 'Mypage', nav: 'UserNav', label: <Icon name="user" size={27} color={getIconColor('Mypage')} /> },
  ];

  return (
    <View>
      {tabs.map(tab => (
        <TouchableOpacity
          key={tab.key}
          onPress={() => {
            setCurrentTab(tab.key as TabName);
            navigation.reset({
              index: 0,
              routes: [
                {
                  name: tab.nav,
                  state: {
                    routes: [{ name: tab.key }],
                  },
                },
              ],
            });
          }}>
          {tab.label}
        </TouchableOpacity>
      ))}
    </View>
  );
};
  • style은 제외한 코드입니다.

  • navigation.reset을 사용해 각 탭을 눌렀을 때, stack이 쌓이지 않고 초기화 되면서 이동하도록 했습니다.

  • 이렇게 하면 각 탭을 누르면 각 stack의 초기 페이지로 이동하게 되면서 페이지 간 이동이 원활히 됩니다.

profile
초보 프론트엔드 개발자 입니다

0개의 댓글