import { DarkTheme, DefaultTheme, NavigationContainer } from '@react-navigation/native';
const isDark = useColorScheme() === "dark";
return (
<NavigationContainer
onReady={onLayoutRootView}
theme={isDark ? DarkTheme : DefaultTheme}
>
<Tabs/>
</NavigationContainer>
);
DarkTheme 는 다크 모드의 스타일을 자동적으로 지원해 줍니다.
DefaultTheme 는 라이트 모드의 스타일을 자동적으로 지원해 줍니다.
이전에 App.js 에서 적용했던 const [loaded] = Font.useFonts(Ionicons.font) 덕분에 Ionicons 을 다른 파일에서 빠르게 불러올 수 있습니다.
Ionicons 을 쓰고 싶은 폴더에 들어가서 import { Ionicons } from '@expo/vector-icons'; 을 불러온 뒤에 options 에 tabBarIcon 을 적용하면 됩니다.
<Tab.Navigator initialRouteName='Movies' >
<Tab.Screen
name='Movies'
component={Movie}
options={{
tabBarIcon: ({focused, color, size}) => {
return <Ionicons name={focused ? "film" : "film-outline"} color={color} size={size}/>
}
}}
/>
이때 focused , color, size 파라미터를 쓸 수 있는데 focused 는 해당 Tab 이 활성화 된 경우 true 를 반환하고 color 은 색을, size 는 크기를 조정할 수 있습니다.
이를 이용해서 focused 상태가 true 일때 삼항 연산자를 통해서 특정 기능을 추가할 수도 있습니다.
react-navigation 에서 제공하는 Navigaters 부분에서 Stack 은 js 로 구성되어 있기 때문에 ios, android 에서 제공하는 navigater 보다 성능면에서 안좋을 수 있습니다.
하지만 바로 밑에 Native Stack 은 ios 에서 제공하는 UINavigationController 이나 android 에서 제공하는 Fragment 를 이용하여 구현했기 때문에 성능면에서 우수합니다.
설치
npm install @react-navigation/native-stack
사용방법
사용하기에 앞서 "@react-navigation/native-stack" 을 불러와야 합니다.
import { createNativeStackNavigator } from "@react-navigation/native-stack";
이렇게 불러오면 나머지 사용법은 Tab Navigater 이랑 비슷합니다.
const NativeStack = createNativeStackNavigator();
const Stack = () => {
return (
// ScreenOne 은 ScreenOne.js 파일 입니다.
<NativeStack.Navigator>
<NativeStack.Screen name='One' component={ScreenOne}/>
<NativeStack.Screen name='Two' component={ScreenTwo}/>
<NativeStack.Screen name='Three' component={ScreenThree}/>
</NativeStack.Navigator>
)
}
export default Stack
저 코드는 가장 기본적인 코드라 어떤 옵션을 적용해야 더 멋진 Stack 을 사용할 수 있습니다.
navigate 는 특정 파일로 이동하고 싶을때 사용합니다.
goBack 은 특정 파일로 이동하기 전 상태로 돌아갑니다.
setOptions 는 Tab Navigater 의 screenOptions 와 똑같은 기능을 수행합니다.
const ScreenOne = ({navigation}) => ( // 밑에 코드처럼 {navigation: { navigate }} 로 쓰자.
<TouchableOpacity onPress={() => navigation.navigate("Two")}>
<Text>One</Text>
</TouchableOpacity>
)
const ScreenTwo = ({navigation: { navigate }}) => (
<TouchableOpacity onPress={() => navigate("Three")}>
<Text>Two</Text>
</TouchableOpacity>
)
const ScreenThree = ({navigation: { goBack}}) => (
<TouchableOpacity onPress={() => goBack()}>
<Text>Go Back</Text>
</TouchableOpacity>
)
const ScreenEnd = ({navigation: { setOptions }}) => (
<TouchableOpacity onPress={() => setOptions({ title: "hello" })}>
<Text>Go Back</Text>
</TouchableOpacity>
)
stack 기능과 tab 기능을 같이 쓰고 싶다면 Root navigater 을 설정해서 사용하면 됩니다.
// Root.js
import React from 'react'
import { createNativeStackNavigator } from "@react-navigation/native-stack";
import Tabs from './Tabs';
import Stack from './Stack';
const Nav = createNativeStackNavigator();
const Root = () => {
return (
// headerShown : false 를 해야 중복 header 가 나오지 않기 때문이다.
<Nav.Navigator screenOptions={{presentation: "modal", headerShown: false}}>
<Nav.Screen name='Tabs' component={Tabs}/>
<Nav.Screen name='Stack' component={Stack}/>
</Nav.Navigator>
)
}
export default Root
// -----------------------------------------------------------------------------
// App.js
return (
<NavigationContainer onReady={onLayoutRootView}>
<Root/>
</NavigationContainer>
);
// -----------------------------------------------------------------------------
// 이렇게 설정하고 난 뒤에 Tabs.js 에 있는 Tab.Screen 경로의 파일을 수정하면 됩니다.
<Tab.Screen
name='Movies' <------ 이부분
component={Movie}
// Movies.js
import React from 'react';
import { View, Text, TouchableOpacity } from 'react-native';
const Movie = ({navigation: {navigate}}) => (
<TouchableOpacity
style={{flex: 1, justifyContent: "center", alignItems: "center"}}
onPress={() => navigate("Stack", {screen: "One"})}
>
<Text>Movie</Text>
</TouchableOpacity>
)
export default Movie;
navigate("", {screen: ""})
<TouchableOpacity
style={{flex: 1, justifyContent: "center", alignItems: "center"}}
onPress={() => navigate("Stack", {screen: "One"})}
>
Navigater 에서 다른 Navigater 로 이동하고 싶을 때 사용합니다.
여기서 navigate("", {screen: ""}) 문법은 어디로 가는지 방향을 알려주는 방법입니다.
예를 들어 화장실로 가려면 편의점으로 들어가서 오른쪽으로 걸어가면 있어 라는 말과 똑같습니다.
react-native 에서 스타일링 해주는 도구 중 styled-components 를 사용하면 된다.
import React from 'react';
import styled from 'styled-components/native';
const Movie = ({navigation: {navigate}}) => (
<Btn onPress={() => navigate("Stack", {screen: "One"})}>
<Title seleted={true}>Movie</Title>
</Btn>
)
const Btn = styled.TouchableOpacity`
flex: 1;
justify-content: center;
align-items: center;
`
const Title = styled.Text`
color: ${props => props.seleted ? "orange" : "black"};
`
export default Movie;
styled-components 의 장점은 항상 react-native 에서 View, Text 등을 꺼내오지 않아도 된다는 것입니다. styled-components 만 불러와도 View, Text 등을 사용할 수 있습니다.
여기서 중요한 부분은 import styled from 'styled-components/native';
라고 불러올 때 /native 를 꼭 붙여주자.
스타일을 전역적으로 사용하고 싶을 때 ThemeProvider 을 사용하면 된다.
여기서 엄청 중요한 부분은 ThemeProvider 을 불러올 때 자동 불러오기를 하면
import { ThemeProvider } from '@react-navigation/native' 로 나옵니다.
하지만 import { ThemeProvider } from 'styled-components/native';
이걸로 해야 합니다.
//Styled.js
export const lightTheme = {
mainBgColor: "white",
textColor: "#1e272e",
};
export const darkTheme = {
mainBgColor: "#1e272e",
textColor: "#d2dae2",
};
//App.js
return (
<ThemeProvider theme={isDark ? darkTheme : lightTheme}>
<NavigationContainer onReady={onLayoutRootView}>
<Root/>
</NavigationContainer>
</ThemeProvider>
);
//Movie.js
import React from 'react';
import styled from 'styled-components/native';
const Movie = ({navigation: {navigate}}) => (
<Btn onPress={() => navigate("Stack", {screen: "One"})}>
<Title seleted={true}>Movie</Title>
</Btn>
)
const Btn = styled.TouchableOpacity`
flex: 1;
justify-content: center;
align-items: center;
background-color: ${props => props.theme.mainBgColor}; <-- 사용
`
const Title = styled.Text`
color: ${props => props.theme.textColor}; <-- 사용
`
export default Movie;