일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- 상태관리
- 인스타그램
- react native
- 비전공
- react-native
- 국비지원
- 프론트 엔드
- ffmpeg
- react
- Spring
- 클론코딩
- 리엑트
- 개발
- 스타트업
- 국비 지원
- 풀스택
- 리엑트 네이티브
- Java
- 스프링
- Redux
- 스프링 부트
- 개발자
- 자바
- 프론트엔드
- 백엔드
- expo
- 비전공자
- 코딩
- spring boot
- 풀스택 개발자
- Today
- Total
오티스의개발일기
[REACT NATIVE] 인스타그램 클론 코딩 (14) gorhom/bottom-sheet 를 활용한 바텀 시트 만들기 본문
[REACT NATIVE] 인스타그램 클론 코딩 (14) gorhom/bottom-sheet 를 활용한 바텀 시트 만들기
안되면 될때까지.. 2023. 1. 1. 23:26
< 이전글
2023.01.01 - [개발/react-native] - [REACT NATIVE] 인스타그램 클론 코딩 (13) 마이페이지 ui 만들기
다음글 >
2023.01.02 - [개발/react-native] - [REACT NATIVE] 인스타그램 클론 코딩 (15) 로그아웃 구현하기
오늘은 gorhom/bottom-sheet 를 활용하여 바텀 시트를 만들어볼것이다
원래는 로그아웃까지 구현하는 포스팅을 올리려했는데
너무 길어질것같아 오늘은 ui만 제작 해보려고한다.
이거 지금 두번쓰는 중이다....
티스토리 이놈.... 임시저장했는데 없어져버렸다......
화가나지만 마음을 가다듬고 시작해보겠다..
# 오늘 작업할 파일목록
- App.js
- babel.config.js
- BottomNavigation.js
- myPageBottomSheet.js
- Header.js(/src/screens/myPage/Header.js)
# 0. 폴더 구조
일단 라이브러리를 다운로드 받아보도록 하겠다.
터미널을 열고 명령어를 작성해보자.
yarn add @gorhom/bottom-sheet@^4
yarn add react-native-reanimated react-native-gesture-handler
라이브러리를 다받았으면 설정해야하는 파일이 몇개가있다.
첫번째는 babel.config.js 파일이다.
module.exports = {
presets: ['module:metro-react-native-babel-preset'],
plugins: ['react-native-reanimated/plugin'], // <---- 추가한것
};
주석으로 적어놨으니 확인하기바란다.
reanimated 라이브러리를 사용하려면 플러그인에 등록해야하는 하지않으면 오류가 뜰것이다.
두번째는 react-native-gesture-hanlder 모듈이다.
이게 이번에 바뀐거같다.
이 제스처 모듈을 사용하려면 루트 파일 상단에 감싸줘야한다.
이것때문에 한 삼십분은 삽질한거같다 ㅎㅎ
import {Provider} from "react-redux";
import store from "./store";
import { StyleSheet, Text, View } from 'react-native'
import AuthNavigaitor from './src/navigations/AuthNavigaiton'
import {GestureHandlerRootView} from 'react-native-gesture-handler'
import { SafeAreaView } from "react-native";export default function App() {
return (
<Provider store={store}>
<GestureHandlerRootView style={{ flex: 1 }}>
<AuthNavigaitor/>
</GestureHandlerRootView>
</Provider>
);
}
<GestureHandlerRootView><GestureHandlerRootView>
이 태그를 꼭 감싸주도록 하자.
시작하기전 참고사항이있다.
본인은 바텀시트가 바텀네비게이션을 가려야하기때문에
BottomNavigation.js 에 작업을 하였다.
이제 본격적으로 시작해보도록 하겠다.
# 1. BottomNavigation.js
import {createBottomTabNavigator} from '@react-navigation/bottom-tabs'
import React, { useCallback, useMemo, useRef } from 'react';
import {
BottomSheetModal,
BottomSheetModalProvider,
} from '@gorhom/bottom-sheet';
import {ROUTES} from '../constants/routes';
import HomeScreen from '../screens/HomeScreen';
import CartScreen from '../screens/CartScreen';
import MyPageScreen from '../screens/MyPageScreen';
import PlayScreen from '../screens/PlayScreen';
import SearchScreen from '../screens/SearchScreen';
import styled from 'styled-components/native'
import Ionicons from "react-native-vector-icons/Ionicons";
import {BOTTOM_ICONS} from '../constants/icons';
import { useSelector, useDispatch } from 'react-redux';
import bottomSheetSlicer from '../slicers/bottomSheetSlicer'
import MyPageBottomSheet from '../screens/bottomSheet/MyPageBottomSheet'
const Tab = createBottomTabNavigator();
const BottomNavigation = (props) => {
const { navigation } = props; // 네비게이션
const dispatch = useDispatch();
const theme = useSelector((state) => state.themeSlicer.theme);
// ref
const bottomSheetModalRef = useRef(null);
// variables
const snapPoints = useMemo(() => ['25%', '50%'], []);
// callbacks
const handlePresentModalPress = useCallback(() => {
bottomSheetModalRef.current?.present();
}, []);
const handleSheetChanges = useCallback((index) => {
console.log('handleSheetChanges', index);
if (index === -1) {
dispatch(bottomSheetSlicer.actions.updateSlicer({name : 'myPage', active: false}))
}
}, []);
const bottomSheet = useSelector((state) => state.bottomSheetSlicer);
if (bottomSheet.active) {
switch(bottomSheet.name) {
case 'myPage' :
handlePresentModalPress();
break;
}
}
return (
<>
<Tab.Navigator initialRouteName={ROUTES.HOME}
screenOptions={({route}) => ({
headerShown: false,
tabBarShowLabel: false,
tabBarStyle: {
borderTopWidth: 1,
borderTopColor: '#61616236',
height: 90,
padding: 10,
backgroundColor: theme.backgroundColor,
},
tabBarIcon: ({color, size, focused}) => {
let iconName;
if (route.name === ROUTES.HOME) {
iconName = focused ? BOTTOM_ICONS.HOME.activeIcon : BOTTOM_ICONS.HOME.inActiveIcon
} else if (route.name === ROUTES.SEARCH) {
iconName = focused ? BOTTOM_ICONS.SEARCH.activeIcon : BOTTOM_ICONS.SEARCH.inActiveIcon
} else if (route.name === ROUTES.PLAY) {
iconName = focused ? BOTTOM_ICONS.PLAY.activeIcon : BOTTOM_ICONS.PLAY.inActiveIcon
} else if (route.name === ROUTES.CART) {
iconName = focused ? BOTTOM_ICONS.CART.activeIcon : BOTTOM_ICONS.CART.inActiveIcon
} else if (route.name === ROUTES.MYPAGE) {
return <Avatar source={{uri: 'https://i.ibb.co/ZhB1QPv/image.jpg'}}/>
}
return <Ionicons name={iconName} size={28} color={theme.TextColor}/>
}
})}>
<Tab.Screen name={ROUTES.HOME} component={HomeScreen} ></Tab.Screen>
<Tab.Screen name={ROUTES.SEARCH} component={SearchScreen}></Tab.Screen>
<Tab.Screen name={ROUTES.PLAY} component={PlayScreen}></Tab.Screen>
<Tab.Screen name={ROUTES.CART} component={CartScreen}></Tab.Screen>
<Tab.Screen name={ROUTES.MYPAGE} component={MyPageScreen}></Tab.Screen>
</Tab.Navigator>
<BottomSheetModalProvider>
<View>
<BottomSheetModal
ref={bottomSheetModalRef}
index={1}
snapPoints={snapPoints}
onChange={handleSheetChanges}
>
<View>
<MyPageBottomSheet navigation={navigation}/>
</View>
</BottomSheetModal>
</View>
</BottomSheetModalProvider>
</>
)
}
const Avatar = styled.Image`
width: 32px;
height: 32px;
border-radius: 50px;
border-width: 2px;
border-color: white;
`;
const View = styled.View``
const Text = styled.Text``
const Button = styled.Button``
export default BottomNavigation
기본적으로 어떤 바텀 네비게이션이 추가될지몰라
BottomNavigation 에 중점을 두고 myPageBottomSheet.js 라는 파일을 따로 빼두었다.
# 2.myPageBottomSheet.js
import styled from "styled-components/native";
import React from 'react'
import {Divider} from 'react-native-elements'
import Ionicons from "react-native-vector-icons/Ionicons";
import {ICONS} from '../../constants/icons'
import {Alert} from 'react-native'
import { useDispatch, useSelector } from "react-redux"; // userDispatch = 데이터 변경시 사용 // useSelector = 데이터 가져올때 사용
import {logOutRequest} from '../../actions/userAction'
import * as $Util from '../../constants/utils'
const myPageBottomSheet = ({navigation}) => {
const dispatch = useDispatch();
const openLogOutAlert = () => {
return (
Alert.alert(
'로그아웃 하시겠습니까?',
'로그아웃',
[
{
text: '로그아웃',
onPress: () => {dispatch(logOutRequest(navigation))}
},
{
text: '취소',
style: "cancel"
},
],
{ cancelable: false }
)
)
}
return (
<Container>
<TouchableOpacity onPress={openLogOutAlert}>
<Box>
<TextBox>
<Ionicons name="log-out-outline" size={28} color="black" />
<Text>로그아웃</Text>
</TextBox>
<Divider width={1}/>
</Box>
</TouchableOpacity>
</Container>
)
}
export default myPageBottomSheet
const Container = styled.View`
padding: 10px 15px;
`
const Box = styled.View``
const TextBox = styled.View`
flex-direction: row;
align-items: center;
margin-bottom: 10px;
`
const Text = styled.Text`
margin-left: 10px;
`
const TouchableOpacity = styled.TouchableOpacity`
`;
자이제 동적하는지 확인해보겠다.
정상적으로 동작하는걸 확인할수있다.
이것으로 포스팅을 마치도록 하겠다.
다음 포스팅에는 진짜로 로그아웃을 구현할것이니 참고하기 바란다.
# 깃허브 주소
https://github.com/1domybest/react-native-ig-clone.git
다음글 >
2023.01.02 - [개발/react-native] - [REACT NATIVE] 인스타그램 클론 코딩 (15) 로그아웃 구현하기
'개발 > react-native' 카테고리의 다른 글
[REACT NATIVE] 인스타그램 클론 코딩 (16) react-native-paper 사용하여 메뉴바 만들기! (5) | 2023.01.02 |
---|---|
[REACT NATIVE] 인스타그램 클론 코딩 (15) 로그아웃 구현하기 (1) | 2023.01.02 |
[REACT NATIVE] 인스타그램 클론 코딩 (13) 마이페이지 ui 만들기 (1) | 2023.01.01 |
[REACT NATIVE] 인스타그램 클론 코딩 (12) AsyncStorage 를 사용하여 jwt 토큰 저장하기 (1) | 2023.01.01 |
[REACT NATIVE] 리엑트 네이티브 인스타그램 클론 코딩 (9) 구글 로그인후 데이터베이스에 저장하기 + 예외 처리를 통한 비동기 처리 -git 참조- (2) | 2022.12.30 |