리액트 네이티브 - 2

박찬영·2024년 4월 2일
post-thumbnail

DarkTheme , DefaultTheme

import { DarkTheme, DefaultTheme, NavigationContainer } from '@react-navigation/native';

  const isDark = useColorScheme() === "dark";

  return (
    <NavigationContainer 
      onReady={onLayoutRootView} 
      theme={isDark ? DarkTheme : DefaultTheme}
    >
      <Tabs/>
    </NavigationContainer>
  );

DarkTheme 는 다크 모드의 스타일을 자동적으로 지원해 줍니다.
DefaultTheme 는 라이트 모드의 스타일을 자동적으로 지원해 줍니다.

icon 적용하기

이전에 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 일때 삼항 연산자를 통해서 특정 기능을 추가할 수도 있습니다.

stack navigater

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 합치기

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: ""}) 문법은 어디로 가는지 방향을 알려주는 방법입니다.
예를 들어 화장실로 가려면 편의점으로 들어가서 오른쪽으로 걸어가면 있어 라는 말과 똑같습니다.

styled-components

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 를 꼭 붙여주자.

theme

스타일을 전역적으로 사용하고 싶을 때 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;
profile
오류는 도전, 코드는 예술

0개의 댓글