jineecode

React navigation (2) 본문

React native

React navigation (2)

지니코딩 2022. 5. 23. 12:35

https://jineecode.tistory.com/260

 

React navigation (1)

1. NavigationContainer import {NavigationContainer} from '@react-navigation/native'; navigation tree를 관리하고 navigation state를 포함하는 구성 요소. 이 구성 요소는 모든 네비게이터 구조를 랩핑해야..

jineecode.tistory.com

 

먼저, 내비게이션은 기본적으로 '스택'으로 쌓이기 때문에, 본인이 개발하고자하는 앱의 내비게이션의 흐름을 잘 파악해야 손이 덜 간다.

스택을 제대로 구분하여 나누지 않는다면 부자연스러운 흐름을 직면할 수밖에 없다.

앱의 정책마다 스택의 흐름이 다르고 아래보다 더 좋은 방법이 있을 수 있다.

 

0. index

import {createStackNavigator} from '@react-navigation/stack';
import {NavigationContainer} from '@react-navigation/native';
import {RootTab} from './RootTab';
const Stack = createStackNavigator();
      <NavigationContainer>
        <Stack.Navigator
          screenOptions={{
            headerShown: false,
          }}>
          <Stack.Screen name="RootTab" component={RootTab} />
        </Stack.Navigator>
      </NavigationContainer>

가장 근본이 되는 navigation index.tsx.
Root인 NavigationContainer가 존재한다.
코드가 너무 길어져서 나누었지만, App.tsx에 적어도 무방하다.

 

1. RootTab

  • 여기엔 크게 로그인 화면(AuthStack)과 메인 화면(BottomTab)이 나뉘어져 있다.
    • AuthStack에는 로그인, 아이디 비밀번호 찾기, 회원가입 등 auth가 필요없는 페이지들로만 구성되어있다. 즉, 로그인을 하면 볼 일이 없는 screen이다.
    • BottomTab은 크게 세 가지의 Navigator로 나뉘어져 있다. 홈, 날씨, 설정. 각각의 Bottom Screen을 대분류로 삼고, 그 아래에 Tree처럼 뻗어나가는 방식을 사용했다.
  • 로그인이 성공하면 BottomTab을, 아니라면 AuthStack을 보여주면 된다.
  • Redux를 사용하고 있다는 전제하에 다음처럼 개발한다. (isLogInSuccess 는 로그인의 useSelector 이다)
  • 이렇게 해주면 내비게이터도 가벼워지고 로그인한 사용자는 로그아웃하지 않는 이상 AuthStack으로 가지 못해서 버그를 방지할 수 있다.
    <Stack.Navigator
      screenOptions={{
        headerShown: false,
      }}>
      {isLogInSuccess ? (
        <Stack.Screen name="BottomTab" component={BottomTab} />
      ) : (
        <Stack.Screen name="AuthStack" component={AuthStack} />
      )}
    </Stack.Navigator>

2. AuthStack

  • 앞서 말한 것처럼 로그인 화면의 구조는 Login, SignUp, FindId 등의 Screen이 모여있는 내비게이터다.
  • 이 앱은 One thing per page UX를 갖추고 있어서 Screen이 몹시 많다. 컴포넌트로 쪼갤 수 있는 건 최대한 쪼개는 게 좋다.
  • Stack.Screen 자체를 컴포넌트로 만들어 썼는데, 이렇게 할 경우 기능 추가를 하거나 개별적으로 커스텀을 할 때 혼란이 올 수 있다. 취향껏 개발하자!
import {useNavigation} from '@react-navigation/native';
import IconCloseImg from '~/assets/images/icon_navigation_close.svg';
import {GoToButtonWrapper} from '~/components/styles/Mixin';
import NavigationModal from '~/components/atoms/Modal/NavigationModal';

export const Features = ({
  name,
  screen,
  customOptions,
  isDepth,
  isRight,
  isModal,
  listeners,
  initialParams,
}: Iprops) => {
  return (
    <Stack.Screen
      name={name}
      component={screen}
      listeners={listeners}
      initialParams={initialParams}
      options={() => ({
        headerTintColor: '#000000',
        headerTitleStyle: {
          fontWeight: 'bold',
          fontSize: Theme.fontSize(18),
        },
        headerLeft: () =>
          isDepth ? (
            <GoToButtonWrapper onPress={() => GoToBack} activeOpacity={0.5}>
              <GoToBack isModal={isModal} />
            </GoToButtonWrapper>
          ) : null,
        headerRight: () =>
          isRight && (
            <GoToButtonWrapper activeOpacity={0.5}>
              <GoToButton screenName="LogIn" />
            </GoToButtonWrapper>
          ),
        ...customOptions,
      })}
    />
  );
};


const SignUpModal = ({navigation}) => {
  return (
    <NavigationModal
      isTwoBtn
      isSubTitle
      label="확인"
      navigation={navigation}
      modalTextLabel={'회원가입을 중단하고 나가시겠어요?'}
      clearDispatch={userClear()}
      navigationScreen={'LogIn'}
    />
  );
};

const SignUpHeaderRight = () => {
  const navigation = useNavigation();

  return {
    title: '회원가입',
    headerBackTitleVisible: false,
    headerTitleAlign: 'left',
    headerRight: () => (
      <GoToButtonWrapper activeOpacity={0.5}>
        <IconCloseImg
          onPress={(e) => {
            e.preventDefault();
            navigation.navigate('SignUpModal');
          }}
        />
      </GoToButtonWrapper>
    ),
    presentation: 'transparentModal',
  };
};



export const AuthStack = () => {
  return (
    <Stack.Navigator>
      {Features({
        name: 'LogIn',
        screen: LogIn,
        customOptions: {headerShown: false},
      })}
      {Features({
        name: 'SignUpModal',
        screen: SignUpModal,
        customOptions: SignUpHeaderRight(),
        isDepth: true,
        isRight: true,
      })}
      {Features({
        name: 'SignUpTerms',
        screen: SignUpTerms,
        customOptions: SignUpHeaderRight(),
        isDepth: true,
        isRight: true,
      })}
      ...
    </Stack.Navigator>
  );
};

3. BottomTab

  • 바텀탭은 3가지 Tab으로 나뉘어져 있다.
  • 각각의 커다란 탭 안에서 Screen으로 다시 쪼개주면 된다.
  • ex) WeatherTab
    • Weather
      • Past
      • Today
      • Forcast
    • WeatherTutorial

export const BottomTab = () => {

  return (
    <Tab.Navigator
      initialRouteName="HomeTab"
      screenOptions={{
        headerShown: false,
        tabBarLabelStyle: {
          fontSize: Theme.fontSize(12),
        },
        tabBarStyle: {
          height: 56,
          paddingTop: Theme.height(5),
          paddingBottom: Theme.height(5),
        },
        tabBarHideOnKeyboard: true,
        tabBarActiveTintColor: '#005500',
      }}>
      <Tab.Screen
        name="HomeTab"
        component={HomeTab}
        options={{
          tabBarLabel: '홈',
          tabBarIcon: ({focused}) => (focused ? <IconHomeAct /> : <IconHome />),
        }}
      />
      <Tab.Screen
        name="WeatherTab"
        component={WeatherTab}
        listeners={({navigation}) => ({
          tabPress: (e) => {
            if (!hasFarmlands) {
              e.preventDefault();
              navigation.navigate(`NoFarmModal${navigation.getState().index}`);
            }
          },
        })}
        options={{
          tabBarLabel: '날씨',
          tabBarIcon: ({focused}) =>
            focused ? <IconWeatherAct /> : <IconWeather />,
        }}
      />
      <Tab.Screen
        name="SettingTab"
        component={SettingTab}
        options={{
          tabBarLabel: '설정',
          tabBarIcon: ({focused}) =>
            focused ? <IconSettingAct /> : <IconSetting />,
        }}
      />
    </Tab.Navigator>
  );
};

 

'React native' 카테고리의 다른 글

react-native toast 사용하기 [react-native-toast-message]  (0) 2022.05.24
React navigation (3)  (0) 2022.05.23
React navigation (1)  (0) 2022.05.23
RN 반응형 디자인 적용법  (0) 2022.02.17
각종 에러들 타파하기  (0) 2022.02.09
Comments