Navigation (1) : 기본, Stack

Sang heon lee·2022년 3월 14일
0

화면전환을 위하여
ReactNavigation 또는 React Native Navigation 을 사용한다.

1. 공식문서

2. 기본 구조

<NavigationContainer>
 <Navigator>
   <Screen name="Home" component={Home}/>
   <Screen name="Item" component={Item}/>
 </Navigator>
</NavigationContainer>

Screen 속성

<Screen name="Home" component={Home}/>

의 Home Component에는 아래 2가지 props 가 항상 전달된다.

const Home = ({navigation, route}) => {
  ...
}

3. 네비게이터의 종류

  • Stack (옆에서 다음 화면이 넘어오는 느낌)
  • Tab (화면 아래에 메인 메뉴가 있어서 클릭하여 이동)
  • Drawer (왼쪽 끄트머리에서 손을 끌어서 메뉴바를 보이는 느낌)

설치 라이브러리

Stack Navigator

  • 자료구조 중 Stack의 개념(입/출구가 한개로 쌓이는 형태)으로 화면 전환이 이루어 진다.

기본 구성

// /navigator/index.js
import React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import StackNav from '../navigations/Stack';

const Navigation = () => {
  return (
    <NavigationContainer>
      <StackNav />
    </NavigationContainer>
  );
};

export default Navigation;
// /navigator/Stack.js
import React from 'react';
import { createStackNavigator } from '@react-navigation/stack';
import { Home, List, Chat } from '../screens';

const Stack = createStackNavigator();

const StackNav = () => {
  return (
    <Stack.Navigator initialRouteName="Home">  // 초기화면 지정 ⭐️⭐️
      <Stack.Screen name="Home" component={Home} />
      <Stack.Screen name="List" component={List} />
      <Stack.Screen name="Chat" component={Chat} />
    </Stack.Navigator>
  );
};

export default StackNav;
// /navigator/App.js
import Navigation from '../navigations';

export default function App() {
  return <Navigation />;
}

화면 이동

// /screens/Home.js
import React from 'react';
import styled from 'styled-components/native';
import Button from '../components/Button';

const Container = styled.View`
  align-items: center;
`;

const StyledText = styled.Text`
  font-size: 30px;
  margin: 10px;
`;

const Home = ({ navigation }) => {
  return (
    <Container>
      <StyledText>Home</StyledText>
      <Button
        title="List"
        onPress={() => {
          navigation.navigate('List');
        }}
      ></Button>
    </Container>
  );
};

export default Home;

화면 이동 with Params

// /src/screens/List.js
import React from 'react';
import styled from 'styled-components/native';
import Button from '../components/Button';

const Container = styled.View`
  flex: 1;
  align-items: center;
  justify-content: center;
  background-color: #ffffff;
`;

const StyledText = styled.Text`
  font-size: 30px;
  margin: 10px;
`;

const items = [
  { id: 1, name: 'react Native' },
  { id: 2, name: 'expo' },
  { id: 3, name: 'react Navigation' },
];

const List = ({ navigation }) => {
  return (
    <Container>
      <StyledText>Home</StyledText>
      {items.map(({ id, name }) => (
        <Button
          key={id}
          title={name}
          onPress={() => {
            navigation.navigate('Chat', { id, name });
          }}
        />
      ))}
    </Container>
  );
};

export default List;
// src/screens/Chat.tsx

import React from 'react';
import styled from 'styled-components/native';
import Button from '../components/Button';

const Container = styled.View`
  align-items: center;
  flex: 1;
  justify-content: center;
`;

const StyledText = styled.Text`
  font-size: 30px;
  margin: 10px;
`;

const Chat = ({ route }) => {    // ⭐️⭐️⭐️
  return (
    <Container>
      <StyledText>Chat</StyledText>
      <StyledText>{route.params.id}</StyledText>
      <StyledText>{route.params.name}</StyledText>
      <Button title="Chat" />
    </Container>
  );
};

export default Chat;

화면 이동 with 특정 route를 가진 상태로

// screens/Chat.js
import React from 'react';
import styled from 'styled-components/native';
import Button from '../components/Button';

const Container = styled.View`
  align-items: center;
  flex: 1;
  justify-content: center;
`;

const StyledText = styled.Text`
  font-size: 30px;
  margin: 10px;
`;

const Chat = ({ navigation, route }) => {
  return (
    <Container>
      <StyledText>Chat</StyledText>
      <StyledText>{route.params.id}</StyledText>
      <StyledText>{route.params.name}</StyledText>
      <Button
        title="Home"
        onPress={() =>
          navigation.reset({
            routes: [{ name: 'Home' }, { name: 'List' }], // ⭐️⭐️⭐️ Home, List 스택을 가진 상태로
            // routes: [{ name: 'Home' }], // ⭐️⭐️⭐️ 스택이 초기화된 Home 으로 돌아가자고 할때
          })
        }
      />
    </Container>
  );
};

export default Chat;

특정 Screen 옵션 주기

// /navigations/Stack.js
const StackNav = () => {
  return (
    // <Stack.Navigator initialRouteName='Home'>
    <Stack.Navigator>
      <Stack.Screen
        name="Home"
        component={Home}
        options={{ cardStyle: { backgroundColor: '#ffffff' } }}
      /> // ⭐️⭐️⭐️ 'Home' screen 에만 배경색상 지정
      <Stack.Screen name="List" component={List} />
      <Stack.Screen name="Chat" component={Chat} />
    </Stack.Navigator>
  );
};

종속하는 모든 Screen 옵션 주기

// /navigations/Stack.js
const StackNav = () => {
  return (
    // <Stack.Navigator initialRouteName='Home'>
    <Stack.Navigator
      screenOptions={{ cardStyle: { backgroundColor: '#ffffff' } }} // ⭐️⭐️⭐️ 모든 screen 에만 배경색상 지정
    >
      <Stack.Screen
        name="Home"
        component={Home}
      /> 
      <Stack.Screen name="List" component={List} />
      <Stack.Screen name="Chat" component={Chat} />
    </Stack.Navigator>
  );
};

메인 페이지 헤더 삭제

// /navigations/Stack.js
const StackNav = () => {
  return (
    // <Stack.Navigator initialRouteName='Home'>
    <Stack.Navigator
      screenOptions={{ cardStyle: { backgroundColor: '#ffffff' } }}
    >
      <Stack.Screen
        name="Home"
        component={Home}
        options={{ headerShown: false }}
      />
      <Stack.Screen name="List" component={List} />
      <Stack.Screen name="Chat" component={Chat} />
    </Stack.Navigator>
  );
};

메인 페이지 헤더 삭제 with 헤치 디자인 고려


// screens/Home.js
import React from 'react';
import styled from 'styled-components/native';
import Button from '../components/Button';
import { SafeAreaProvider, SafeAreaView } from 'react-native-safe-area-context';
import { useSafeAreaInsets } from 'react-native-safe-area-context';

const Container = styled.View`
  align-items: center;
  background-color: #ffffff;
  padding-top: ${({ insets }: { insets: insetType }) => insets.top}px;
  padding-bottom: ${({ insets }: { insets: insetType }) => insets.bottom}px;
  padding-right: ${({ insets: { right } }) => right}px;
  padding-left: ${({ insets: { left } }) => left}px;
`;

const StyledText = styled.Text`
  font-size: 30px;
  margin: 10px;
`;

interface insetType {
  bottom: string;
  left: string;
  right: string;
  top: string;
}

const Home = ({ navigation }) => {
  const insets = useSafeAreaInsets();
  console.log(insets);
  return (
    <Container insets={insets}>
      <StyledText>Home</StyledText>
      <Button
        title="List"
        onPress={() => {
          navigation.navigate('List');
        }}
      />
    </Container>
  );
};

export default Home;

  • insets의 console.log

헤더 타이틀 수정

// /navigations/Stack.js
const StackNav = () => {
  return (
    // <Stack.Navigator initialRouteName='Home'>
    <Stack.Navigator
      screenOptions={{ cardStyle: { backgroundColor: '#ffffff' } }}
    >
      <Stack.Screen
        name="Home"
        component={Home}
        options={{ headerShown: false }}
      />
      <Stack.Screen name="List" component={List} />
      <Stack.Screen
        name="Chat"
        component={Chat}
        options={{ headerTitle: 'chat screen' }}
      />
    </Stack.Navigator>
  );
};
profile
개초보

0개의 댓글