[리액트 네이티브] 스택(stack) 내비게이션, 탭(tab) 내비게이션
my code archive
article thumbnail
반응형

일반적으로 모바일 애플리케이션은 하나의 화면이 아닌, 다양한 화면이 상황에 맞게 전환되면서 나타남.

=> 내비게이션(navigation)은 모바일 애플리케이션에서 가장 중요한 기능 중 하나임!!

=> 리액트 네이티브에서는 내비게이션을 지원하지 않는다. 외부 라이브러리를 이용해야 한다.

 

1. 🤍리액트 내비게이션

  • 리액트 네이티브 애플리케이션의 내비게이션을 쉽고 간단하게 관리할 수 있도록 도와줌
  • 지원하는 내비게이션 종류 : 스택(stack) 내비게이션, 탭(tab) 내비게이션, 드로어(drawer) 내비게이션
  • 구조 : NavigationContainer, Navigator, Screen 컴포넌트
  • Screen 컴포넌트 : 화면으로 사용되는 컴포넌트로, name과 component 속성을 지정해야함. name은 화면 이름, component에는 화면으로 사용될 컴포넌트를 전달함.(화면으로 사용되는 컴포넌트에는 항상 navigaion과 route가 props로 전달됨.)
  • Navigator 컴포넌트 : 화면을 관리하는 중간 관리자 역할. 여러 개의 Screen 컴포넌트를 자식 컴포넌트로 갖고 있음.
  • NavigationContainer : 내비게이션의 계층 구조, 상태를 관리하는 컨테이너 역할. 모든 구성 요소를 감싼 최상위 컴포넌트.

2. 🤍리액트 내비게이션 실습

프로젝트 생성

<javascript />
expo init react-native-navigaion //프로젝트 생성
npm install styled-components //스타일드 컴포넌트 라이브러리 설치

리액트 내비게이션 라이브러리 설치

<javascript />
//라이브러리 설치
npm install --save @react-navigaion/native
//종속성 설치
expo install react-native-gesture-handler react-native-reanimated react-native-screens react-native-safe-area-context @react-native-community/masked-view

전체 디렉토리 구조

2.1. 1. 스택 내비게이션(Stack Navigaion)

  • 가장 많이 사용되는 내비게이션
  • 현재 화면 위에 다른 화면을 쌓으며 화면을 이동하는 것이 특징임. ex) 채팅방 입장, 여러 목록 중 특정 항목의 상세 화면으로 이동
<javascript />
npm install @react-navigation/stack //스택 라이브러리 설치

첫 화면 Home 컴포넌트, 다음 화면인 List 화면으로 이동하기 위한 버튼으로 구성되어 있음.

<javascript />
const Home = () => {
return(
<Container>
<StyledText>Home</StyledText>
<Button title="go to the list screen" />
</Container>
);
};

목록 화면으로 사용할 List 컴포넌트

<javascript />
const items = [
{_id: 1, name: 'React Native'},
{_id: 2, name: 'React Navigation'},
{_id: 3, name: 'JavaScript'},
];
const List = () => {
const _onPress = item => {};
return(
<Container>
<StyledText>List</StyledText>
{items.map(item=>(
<Button
key={item._id}
title={item.name}
onPress={()=>_onPress(item)}
/>
))}
</Container>
);
};
export default List;

Item 컴포넌트에 임시 데이터를 생성 후,

상세 정보를 보여주는 Stack 컴포넌트 작성

=> Navigator 컴포넌트 안에 Screen 컴포넌트를 자식 컴포넌트로 작성, 앞에서 만든 컴포넌트를 Screen 컴포넌트의 component로 지정함. name에는 화면의 이름을 작성하며, Screen 컴포넌트의 name은 반드시 서로 다른 값을 가져야함!

<javascript />
const Stack = createStackNavigator();
const StackNavigation = () => {
return (
<Stack.Navigator>
<Stack.Screen name="Home" component={Home} />
<Stack.Screen name="List" component={List} />
<Stack.Screen name="Item" component={Item} />
</Stack.Navigator>
);
};
export default StackNavigation;

스택 내비게이션에서 첫 번째 화면으로 나오는 화면을 따로 지정하고 싶을 때에는 initialRouteName 속성을 사용함.

<javascript />
<Stack.Navigator initialRouteName="List">
...
</Stack.Navigator>

📱실행 화면

2.2. 2-1. 화면 이동

  • Screen 컴포넌트의 component로 지정된 컴포넌트는 화면으로 이용되고, navigation이 props로 전달됨.
  • navigation의 다양한 기능 중 navigate 함수는 원하는 화면으로 이동하는 데에 사용됨.
  • 전달되는 화면 이름은 Screen 컴포넌트의 name 값 중 하나를 입력해야함!
<javascript />
/*
Home 화면에서 props로 전달되는 navigation을 사용해서 버튼 클릭 시 List 화면으로 이동하도록
*/
const Home = ({navigation}) => {
return(
<Container>
<StyledText>Home</StyledText>
<Button title="go to the list screen"
onPress={()=>navigation.navigate('List')}
/>
</Container>
);
};

📱실행 화면

2.3. 2-2. 상세 화면 이동

  • 상세 화면은 어떤 내용을 렌더링해야 하는지 전달받아야함.
  • navigate 함수를 이용할 때 두 번째 파라미터에 객체를 전달해서 이동하는 화면에 필요한 정보를 함께 전달하는 기능이 있음.

Item 화면으로 이동하면서 항목의 id와 name을 전달하도록 작성. 전달된 내용은 컴포넌트의 props로 전달되는 route의 params를 통해 확인 가능함.

<javascript />
const List = ({navigation}) => {
const _onPress = item => {
//List 화면에서 목록 클릭 시 해당 항목의 정보와 함께 Item 화면으로 이동
navigation.navigate('Detail',{id: item._id, name: item.name});
};

Item 화면에서 전달되는 params를 이용해 화면에 항목의 id와 name 출력하기

📱실행 화면

2.4. 3. 스타일 수정하기

헤더 스타일으 수정하는 속성은 헤더의 배경색을 수정하는 headerStyle, 헤더의 타이틀 컴포넌트의 스타일을 수정하는 headerTitleStyle이 있다.

<javascript />
<Stack.Navigator initialRouteName="Home"
screenOptions={{cardStyle: {backgroundColor: '#ffffff'},
headerStyle: {
height: 110,
backgroundColor: '#95a5a6',
borderBottomWidth: 5,
borderBottomColor: '#34495e',
},
headerTitleStyle: {color: '#ffffff', fontSize: 24},
headerTitleAlign: 'center',
headerTitle: ({ style }) => (
<MaterialCommunityIcons name="react" style={style} />
),
}}
>

📱실행 화면

  • 헤더의 타이틀을 변경하기 위해 문자열을 지정했던 headerTitle 속성에 컴포넌트를 반환하는 함수 지정 시, 타이틀 컴포넌트를 반환하는 컴포넌트로 변경할 수 있음.
  • headerTitle에 함수가 설정되면 해당 함수의 파라미터로 style, tintColor 등이 포함된 객체가 전달됨. => 그 중 style은 headerTitleStyle에 설정된 값, tintColor는 headerTintColor에 지정된 값이 전달된다.

vector-icons에서 제공하는 컴포넌트를 이용하여 리액트 로고가 랜더링되도록 작성.

📱실행 화면

headerLeft, headerRight에 컴포넌트를 변환함수를 지정하여 헤더 양 끝에 원하는 컴포넌트를 렌더링 해보기

  • useLayoutEffect Hook : useEffect Hook과 사용법이 동일하지만, 컴포넌트 업데이트된 직후 화면이 렌더링되기 전에 실행된다는 차이점이 있음. => 화면 렌더링하기 전에 변경할 부분이 있거나 수치 등을 측정해야 하는 상황에서 많이 사용됨.
  • headerLeft의 onPress는 뒤로 가기 버튼 기능이 전달됨.
  • headerRight 함수의 파라미터는 tintColor만 전달되므로 onPress에 원하는 행동을 정의해야함.
  • popToTop 함수는 현재 쌓여있는 모든 화면을 내보내고 첫 화면으로 돌아가는 기능.
<javascript />
const Item = ({navigation, route}) => {
useLayoutEffect(()=>{
navigation.setOptions({
headerBackTitleVisible: false,
headerTintColor: '#ffffff',
headerLeft: ({onPress, tintColor})=>{
return(
<MaterialCommunityIcons
name="keyboard-backspace"
size={30}
color={tintColor}
onPress={onPress}
/>
);
},
headerRight: ({tintColor})=>(
<MaterialCommunityIcons
name="home-variant"
size={30}
style={{marginRight: 11}}
color={tintColor}
onPress={()=>navigation.popToTop()}
/>
),
});
}, []);

📱실행 화면

2.5. 4. 탭 내비게이션(Tab Navigation)

탭 내비게이션은 보통 화면 위 or 아래에 위치하며, 탭 버튼을 누르면 연결된 화면으로 이동하는 방식으로 동작함.

<javascript />
npm install @react-navigation/bottom-tabs //탭 내비게이션 라이브러리 설치

3개의 버튼과 해당 버튼과 해당 버튼에 연결된 화면으로 구성된 탭 내비게이션을 만들 것이며, 먼저 화면으로 사용할 TabScreen 컴포넌트를 작성.

<javascript />
export const Mail = () => {
return(
<Container>
<StyledText>Mail</StyledText>
</Container>
);
};
export const Meet = () => {
return(
<Container>
<StyledText>Meet</StyledText>
</Container>
);
};
export const Settings = () => {
return(
<Container>
<StyledText>Settings</StyledText>
</Container>
);
};

위에서 생성된 컴포넌트를 이용해 탭 내비게이션 구성

<javascript />
const Tab = createBottomTabNavigator();
const TabNavigation = ()=>{
return(
<Tab.Navigator>
<Tab.Screen name="Mail" component={Mail} />
<Tab.Screen name="Meet" component={Meet} />
<Tab.Screen name="Settings" component={Settings} />
</Tab.Navigator>
);
};
export default TabNavigation;

📱실행 화면

2.6. 5. 버튼 아이콘 설정하기

  • 화면을 구성하는 Screen마다 tabBarIcon에 MaterialCommunityIcons 컴포넌트를 반환하는 함수 지정
  • 반환 컴포넌트의 색과 크기는 TabBarIcon에 지정된 함수의 파라미터로 전달되는 color와 size를 이용해 설정
<javascript />
import {MaterialCommunityIcons} from "@expo/vector-icons";
const TabIcon = ({name, size, color})=>{
return <MaterialCommunityIcons name={name} size={size} color={color}/>;
};
const TabNavigation = () => {
return(
<Tab.Navigator
...
>
<Tab.Screen
name="Mail"
component={Mail}
options={{
tabBarIcon: props =>
TabIcon({...props,
name: 'email'
}),
}}
/>
<Tab.Screen
name="Meet"
component={Meet}
options={{
tabBarIcon: props =>
TabIcon({
...props,
name: 'video',
}),
}}
/>
<Tab.Screen
name="Settings"
component={Settings}
options={{
tabBarIcon: props =>
TabIcon({
...props,
name: 'settings',
}),
}}
/>
</Tab.Navigator>
);
};

💡만약 Screen 컴포넌트마다 탭 버튼 아이콘을 지정하지 않고 한 곳에서 모든 버튼의 아이콘을 관리하고 싶을 경우 Navigator 컴포넌트의 screenOptions 속성을 사용해서 관리할 수 있다.

<javascript />
//컴포넌트마다 아이콘을 지정하지 않고 한 곳에서 모든 버튼의 아이콘을 관리
// screenOptions={({route})=>({
// tabBarIcon: props => {
// let name = '';
// if (route.name === 'Mail') name = 'email';
// else if (route.name === 'Meet') name = 'video';
// else name = 'settings';
// return TabIcon({...props, name});
// },
// })}

📱실행 화면

+기타 다른 스타일 수정 사항들, 주석 설명

<javascript />
<Tab.Navigator
/*
탭 버튼 순서는 변경하지 않고, 렌더링되는
첫 번째 화면을 변경하고 싶은 경우 : initialRouteName 속성 이용
*/
initialRouteName="Settings"
tabBarOptions={{
//비활성화된 상태 색 설정
//activeTintColor: '#ffffff',
inactiveTintColor: '#0B92E9',
//탭 바 스타일 변경
style: {
backgroundColor: '#54b7f9',
borderTopColor: '#ffffff',
borderTopWidth: 2,
},
//버튼 아이콘의 아래가 아닌 아이콘 옆에 렌더링
labelPosition: 'beside-icon',
//아이콘만 나타나도록
showLabel: false,
}}
>

📱실행 화면

tabBarOptions의 style 속성이 먹히지 않는다ㅠㅠㅠ아직 이유 못찾음...

반응형
profile

my code archive

@얼레벌레 개발자👩‍💻

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!

반응형