[RN] 화면 간 전환 - navigation.navigate vs navigation.push / 서로 다른 탭 간에 특정 페이지와 파라미터를 넘기려면?

fejigu·2023년 8월 4일
2

React Native Project

목록 보기
11/19
post-thumbnail


📍 navigation.navigate vs navigation.push

→ 1)navigation.navigatenavigation.push는 React Navigation 라이브러리에서 화면 간 전환을 처리하는 데 사용되는 두 가지 메서드이다.
처음에 화면 간 전환을 처리하는데 navigation.navigate만 사용했다. 하지만 각각의 메서드가 적합한 경우가 있었다. 내가 이해한 바를 정리해두고 프로젝트에 적용하고자 한다.

일단 각각에 대해 알아보면 아래와 같이 정리된 경우를 많이 볼 수 있었다.

✔️ navigation.navigate 사용 사례

  • 주로 스택 내의 화면 전환에 사용된다.
  • 동일한 화면을 여러 번 중복해서 스택에 쌓지 않아야 할 때 사용된다.
  • 이전 화면으로 돌아갈 때 주로 사용됩니다. (navigation.goBack() 또는 navigation.pop()와 함께 사용)

    ✔️ navigation.push 사용 사례
    같은 화면을 여러 번 중복해서 스택에 쌓아야 할 때 사용된다.
    동일한 화면에 다른 데이터나 상태를 전달하여 여러 인스턴스를 표시해야 할 때 유용하다. 예를 들어, 게시물 목록 화면에서 각 게시물에 대한 상세 정보를 동일한 게시물 상세 화면으로 여러 번 열어야 할 때 navigation.push를 사용할 수 있다.

    [예시 코드]
// navigation.navigate 
navigation.navigate('ScreenA'); // ScreenA로 이동, 스택 유지
// navigation.push 
navigation.push('ScreenA'); // ScreenA로 이동, 스택에 새로운 'ScreenA' 추가

→ 2) 하지만 이렇게 정리하는 것도 프로젝트에서 내가 어떻게 화면 간 전환을 관리해야할 지 감이 잡히지 않았다. 그래서 내가 구현해야하는 프로세스와 스크인에 적용하여 어떻게 적용해야할 지 감이 잡아 보았다.

🔎 먼저 위와 같이 회원가입을 하는 프로세스에서는 navigation.push를 사용하는 것이 적합할 것 같았다.

전화번호를 입력하는 스크린에서 이름과 주소를 입력하는 스크린으로 이동한 후에 다시 전화번호 스크린으로 돌아와야 할 수 도 있기 때문이다.그래서 navigation.push를 사용하여 스택에 새로운 인스턴스를 추가하여 이동하는 것이다. 그러면 사용자가 이름과 주소를 입력하는 스크린에서 뒤로가기 버튼을 누르면 이전 스크린으로 쉽게 되돌아갈 수 있다.

⭐️⭐️⭐️ + 다시 고민해보니 과거 스택으로 돌아가는 경우 차라리 .back() 함수를 사용하는 것이 나을 것 같다....

~~🔎 하지만 위와 같은 프로세스에서는 navigation.navigate를 사용하는 것이 적합해보인다.

앱 푸시 동의를 받는 화면에서 사용자가 동의 버튼을 누르면 회원가입 프로세스가 종료되고, 즉시 다른 홈 스크린으로 이동해야하는 경우이다. 이 경우(회원가입이 완료된 경우)에는 더 이상 이전 스크린(회원가입 프로세스 스크린들)으로 돌아가지 않기 때문에 새로운 인스턴스를 스택에 쌓을 필요가 없는 것이다. ~~

⭐️⭐️⭐️ + 다시 고민을 해보니 회원가입 프로세스에서 .reset() 이라는 함수를 활용하는 것이 나을 것 같다.. 그래야 로그인 시 홈으로 이동하고나서 뒤로가기를 없앨 수 있으니깐!(다시 로그인 화면으로 돌아가기 방지)

import { CommonActions } from '@react-navigation/native';
// 회원가입 완료 후 홈 화면으로 리다이렉트
const resetAction = CommonActions.reset({
  index: 0,
  routes: [{ name: 'Home' }],
});
navigation.dispatch(resetAction);

⭐️⭐️⭐️ 추가 내용 !!

→ 스택에 이미 스크린이 있으면 해당 스크린으로 돌아가는 부분 : .navigate()
→ 무조건 스택에 스크린을 추가하는 방식 : .push()
→ .navigate() 같은 경우는 과거 페이지로 돌아가면서 스택에 쌓인 스크린을 제거한다.


ex) 특수한 이벤트 페이지 일 경우 STEP가 5까지 있는데, 사용자가 닫기 버튼을 누를경우 STEP 1으로 모두 돌아가거나, 이벤트 페이지를 모두 닫을 수 있다.
STEP 1 닫기 -> 이벤트 페이지 닫기
STEP 2 닫기 -> STEP 1으로 이동
STEP 3 닫기 -> STEP 1으로 이동하고 SETP 2-3 스택에서 제거됨
STEP 4 닫기 -> STEP 1으로 이동하고 SETP 2-4 스택에서 제거됨
STEP 5 닫기 -> STEP 1으로 이동하고 SETP 2-5 스택에서 제거됨



📍 서로 다른 탭 간에 특정 페이지와 파라미터를 넘기려면?

→ 서로 다른 탭 간에 특정 페이지와 파라미터를 넘기기 위해서는 navigate 매서드를 사용하고 필요한 파라미터를 함께 전달하면 되었다.

"우리 프로젝트에서 바텀 탭에 Home 탭에서 Cart 탭의 특정 페이지로 이동하고 싶은데, 특정 파라미터를 함께 넘겨야 하는 상황인 경우를 가정해보자!"

1. 탭 내부의 특정 스크린으로 파라미터를 넘기기 위해 각 스택을 정의한다.

//// CartStack.tsx
import { createStackNavigator } from "@react-navigation/stack";
import React from "react";
import CartScreen from "./CartScreen";
import ItemDetailScreen from "./ItemDetailScreen";

export type CartStackParamList = {
  Cart: undefined;
  ItemDetail: { itemId: string };
};

const Stack = createStackNavigator<CartStackParamList>();

const CartStack = () => {
  return (
    <Stack.Navigator>
      <Stack.Screen name="Cart" component={CartScreen} />
      <Stack.Screen name="ItemDetail" component={ItemDetailScreen} />
    </Stack.Navigator>
  );
};

export default CartStack;

2. 이동하고자 하는 탭 내부의 특정 페이지로 이동할 때 파라미터를 함께 전달한다.

// HomeScreen.tsx
import { useNavigation } from '@react-navigation/native';

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

//navigation.push 또는 nvigation.navigate 메서드를 사용하여 탭 내부의 특정 스크린으로 이동하면서 파라미터를 함께 전달할 수 있다. 
  const goToItemDetailInCart = (itemId: string) => {
    navigation.push('Cart', {
      screen: 'ItemDetail',
      params: { itemId },
    });
  };

  return (
    <View>
      <Text>Home Screen</Text>
      <Button title="Go to Cart Item Detail" onPress={() => goToItemDetailInCart('123')} />
    </View>
  );
};

export default HomeScreen;

3. 이동한 페이지에서 파라미터를 받아 사용한다.

// ItemDetailScreen.tsx
//이렇게 하면 서로 다른 탭 간에 특정 페이지로 이동하면서 파라미터를 전달 할 수 있다. 
import { useRoute } from '@react-navigation/native';

const ItemDetailScreen = () => {
  const route = useRoute();
  const { itemId } = route.params as { itemId: string };

  return <Text>Item ID: {itemId}</Text>;
};

export default ItemDetailScreen;
profile
console.log(frontendjigu( ☕️, 📱); // true

2개의 댓글

comment-user-thumbnail
2023년 8월 4일

이런 유용한 정보를 나눠주셔서 감사합니다.

1개의 답글