[React Native] React Navigation - 11. [Drawer] Custom Component

2022. 1. 19. 19:55React Native/Basic

 

 


 


 


11. [Drawer] Custom Component

 

side drawer를 customize 하는 방법에 대해서 알아보자!

 

CustomDrawerContent를 대체하는 SideDrawer를 만들어보자

sideDrawer를 만든 뒤에 스타일까지 지정하면 스크린 간 이동을 하도록 설정을 추가로 해줘야 한다. 이건 onPress를 해서 이동하는 함수를 사용해주면 된다. 이동하는 함수는 새로 만들어 준다.

 

navigateToScreen = (route) => () => {
    this.props.navigation.dispatch(
      CommonActions.navigate({
        name: route,
        params: {},
      }),
    );
};

route 는 화면 이동을 위해서 파라미터로 받아온 것인데 여기서 arrow function이 2번 쓰인 이유는 뭘까?

arrow 가 2개니까 리턴값이 2개라고 생각하면 되는데 중괄호 안의 값을 리턴하는 함수를 또 리턴값으로 받는 것이다. 그때의 파라미터로 route가 들어가는 것이다. 중괄호 안에 구현할 내용이 state를 업데이트 하는 내용이고, redux에서 배울 텐데 여기서 리턴을 1번만 하게 되면 업데이트가 무한루프에 걸리게 된다. 그래서 함수가 시작할 때 업데이트 behavior를 끊어주기 위한 트리거 장치가 필요하게 되고 그래서 arrow를 2번 쓴 것이다.

 

CommonActions라는 라이브러리는 여러 actions creators를 쓰게 도와주는데 그 중 하나가 navigate라는 액션이다. 특정 route에 이동하게끔 도와주는 액션이다. 이런 액션이 발생하면 dispatch를 통해서 state 값을 업데이트 시켜준다.

 

side drawer를 통해 터치된 route로 이동시키고 그 때 params를 업데이트 시키라는 코드이다.

 

 

home_drawer.js

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 *
 * @format
 * @flow strict-local
 */

import React, {Component} from 'react';
import {StyleSheet, Text, View, Button} from 'react-native';

class DrawerHomeScreen extends Component {
  render() {
    return (
      <View
        style={{
          flex: 1,
          alignItems: 'center',
          justifyContent: 'center',
        }}>
        <Text>Home Screen</Text>
        <Button
          title="To User Screen"
          onPress={() => {
            this.props.navigation.navigate('User');
          }}
        />
      </View>
    );
  }
}

const styles = StyleSheet.create({});

export default DrawerHomeScreen;

user_drawer.js

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 *
 * @format
 * @flow strict-local
 */

import React, {Component} from 'react';
import {StyleSheet, Text, View, Button, Image} from 'react-native';

import {NavigationContainer} from '@react-navigation/native';
import {createNativeStackNavigator} from '@react-navigation/native-stack';
import Logo from './assets/pics/home_icon.png';

class DrawerUserScreen extends Component {
  drawerStyle = () => {
    this.props.navigation.setOptions({
      drawerIcon: () => {
        <Image source={Logo} style={{width: 40, height: 40}} />;
      },
    });
  };
  render() {
    this.drawerStyle();
    return (
      <View
        style={{
          flex: 1,
          alignItems: 'center',
          justifyContent: 'center',
        }}>
        <Text>User Screen</Text>
      </View>
    );
  }
}

const styles = StyleSheet.create({});

export default DrawerUserScreen;

my_drawer.js

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 *
 * @format
 * @flow strict-local
 */

import React, {Component} from 'react';
import {StyleSheet, Text, View, Button, Image} from 'react-native';
import {ScrollView} from 'react-native-gesture-handler';
import Logo from './assets/pics/home_icon.png';
import {CommonActions} from '@react-navigation/native';

class SideDrawer extends Component {
  navigateToScreen = route => () => {
    this.props.navigation.dispatch(
      CommonActions.navigate({
        name: route,
        params: {},
      }),
    );
  };
  render() {
    return (
      <View style={styles.container}>
        <ScrollView>
          <View>
            <View style={styles.imageContainer}>
              <Image source={Logo} style={{width: 40, height: 40}} />
            </View>
            <Text style={styles.sectionHeading}>Section 1</Text>
            <View style={styles.navSectionStyle}>
              <Text
                style={styles.navItemStyle}
                onPress={this.navigateToScreen('Home')}>
                Home
              </Text>
              <Text
                style={styles.navItemStyle}
                onPress={this.navigateToScreen('User')}>
                User
              </Text>
              <Text
                style={styles.navItemStyle}
                onPress={() => {
                  alert('Help Window');
                }}>
                Help
              </Text>
              <Text
                style={styles.navItemStyle}
                onPress={() => {
                  alert('Info  Window');
                }}>
                Info
              </Text>
            </View>
          </View>
        </ScrollView>
        <View style={{paddingLeft: 10, paddingBottom: 30}}>
          <Text>Copyright @ byein, 2022.</Text>
        </View>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    paddingTop: 80,
  },
  imageContainer: {
    alignItems: 'center',
    padding: 50,
  },
  sectionHeading: {
    color: '#fff',
    background: '#ef9de4',
    paddingVertical: 10,
    paddingHorizontal: 15,
    fontWeight: 'bold',
  },
  navSectionStyle: {
    backgroundColor: '#04b6ff',
  },
  navItemStyle: {
    padding: 10,
    color: '#fff',
  },
});

export default SideDrawer;

App.js

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 *
 * @format
 * @flow strict-local
 */

import React, {Component} from 'react';
import {StyleSheet, Text, View, Image, Button, Linking} from 'react-native';
import {DrawerActions, NavigationContainer} from '@react-navigation/native';
import {createNativeStackNavigator} from '@react-navigation/native-stack';
import {
  createDrawerNavigator,
  DrawerContentScrollView,
  DrawerItem,
  DrawerItemList,
} from '@react-navigation/drawer';
import HomeScreen from './src/home';
import UserScreen from './src/user';
import LogoTitle from './src/logo';
import DrawerHomeScreen from './src/home_drawer';
import DrawerUserScreen from './src/user_drawer';
import PictogramHome from './src/assets/pics/home_icon.png';
import SideDrawer from './src/my_drawer';

const Stack = createNativeStackNavigator();
const Drawer = createDrawerNavigator();

// CustomDrawerContent = props => {
//   return (
//     <DrawerContentScrollView {...props}>
//       <DrawerItemList {...props} />
//       <DrawerItem
//         label="Help"
//         onPress={() => Linking.openURL('http://www.google.com')}
//         icon={() => <LogoTitle />}
//       />
//       <DrawerItem label="Info" onPress={() => alert('Info window')} />
//     </DrawerContentScrollView>
//   );
// };

class App extends Component {
  // logoTitle = () => {
  //   return (
  //     <Image
  //       style={{width: 40, height: 40}}
  //       source={require('./src/assets/pics/home_icon.png')}
  //     />
  //   );
  // };

  render() {
    return (
      <NavigationContainer>
        <Drawer.Navigator
          initialRouteName="Home"
          screenOptions={{
            drawerType: 'front',
            drawerPosition: 'right',
            drawerStyle: {
              backgroundColor: '#c6cbef',
              width: 200,
            },
            drawerActiveTintColor: 'red',
            drawerActiveBackgroundColor: 'skyblue',
          }}
          drawerContent={props => <SideDrawer {...props} />}>
          <Drawer.Screen
            name="Home"
            component={DrawerHomeScreen}
            options={{
              drawerIcon: () => {
                <Image
                  source={PictogramHome}
                  style={{width: 40, height: 40}}
                />;
              },
            }}
          />
          <Drawer.Screen name="User" component={DrawerUserScreen} />
        </Drawer.Navigator>
      </NavigationContainer>
      // <NavigationContainer>
      //   <Stack.Navigator
      //     initialRouteName="Home"
      //     screenOptions={{
      //       headerStyle: {
      //         backgroundColor: '#a4511e',
      //       },
      //       headerTintColor: '#ffffff',
      //       headerTitleStyle: {
      //         fontWeight: 'bold',
      //         color: '#f3d612',
      //       },
      //     }}>
      //     <Stack.Screen
      //       name="Home"
      //       component={HomeScreen}
      //       options={{
      //         title: 'Home Screen',
      //         headerTitle: () => <this.logoTitle />,
      //         headerRight: () => (
      //           <Button
      //             title="info"
      //             onPress={() => alert('I am a button!!')}
      //             color="orange"
      //           />
      //         ),
      //       }}
      //     />
      //     <Stack.Screen
      //       name="User"
      //       component={UserScreen}
      //       initialParams={{
      //         userIdx: 50,
      //         userName: 'Gildong',
      //         userLastName: 'Go',
      //       }}
      //       options={{
      //         title: 'User Screen',
      //         headerStyle: {
      //           backgroundColor: 'pink',
      //         },
      //         headerTintColor: 'red',
      //         headerTitleStyle: {
      //           fontWeight: 'bold',
      //           color: 'purple',
      //         },
      //       }}
      //     />
      //   </Stack.Navigator>
      // </NavigationContainer>
    );
  }
}

const styles = StyleSheet.create({});

export default App;

참고 자료

https://www.inflearn.com/course/%EB%A6%AC%EC%95%A1%ED%8A%B8-%EB%84%A4%EC%9D%B4%ED%8B%B0%EB%B8%8C-%EA%B8%B0%EC%B4%88/dashboard

 

iOS/Android 앱 개발을 위한 실전 React Native - Basic - 인프런 | 강의

Mobile App Front-End 개발을 위한 React Native의 기초 지식 습득을 목표로 하고 있습니다. 진입장벽이 낮은 언어/API의 활용을 통해 비전문가도 쉽게 Native Mobile App을 개발할 수 있도록 제작된 강의입니다

www.inflearn.com