일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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
- expo
- spring boot
- ffmpeg
- 인스타그램
- Spring
- 비전공
- 프론트엔드
- 개발자
- 백엔드
- 비전공자
- 풀스택 개발자
- 스프링
- Java
- 스프링 부트
- 개발
- Redux
- 자바
- react
- 프론트 엔드
- 국비 지원
- react native
- 리엑트 네이티브
- 풀스택
- 리엑트
- 스타트업
- 국비지원
- Today
- Total
오티스의개발일기
[REACT NATIVE] 리엑트 네이티브 인스타그램 클론 코딩 (1) 계획 및 프로젝트 네비게이션 생성 및 홈 화면 구현 -git 참조- 본문
[REACT NATIVE] 리엑트 네이티브 인스타그램 클론 코딩 (1) 계획 및 프로젝트 네비게이션 생성 및 홈 화면 구현 -git 참조-
안되면 될때까지.. 2022. 12. 22. 19:50
다음글 >
오늘부터 인스타그램 UI를 직접 제작해볼 계획이다.
인스타그램 클론전에 무작정 만들게아니고 정리를 하고 시작할예정이다.
이번 프로젝트는 spring boot jpa로 서버를 만들어 api통신을 할계획이다.
자세한계획은 밑에 써보겠다.
일단 바쁜 현대사회에 살고있는 우리 개발자들 급한마음 달래고자 오늘 만든 완성본을 보여주도록 하겠다.
프론트
만들어아야 할 네비게이션
네비게이션
[
- 홈
- 찾기
- 릴스 // 아이콘만 만들기만하고 구현은 안할예정
- shop //아이콘만 만들기만하고 구현은 안할예정
- 마이페이지
]
만들어야할 스크린 스택들
홈 피드 리스트,
스토리 리스트,
스토리 디테일,
코멘트(댓글) 리스트,
마이페이지,
프로필 편집창,
피드 디테일,
피드 스크롤 리스트 (마이페이지에서 피드 눌렀을때 스크롤로 나오는 형식),
로그인,
회원가입,
백엔드
회원 crud,
피드 crud,
스토리 crud, // 스토리는 아직 모름
피드 좋아요 기능,
피드 댓글기능,
메시지 기능 // 아직 미정,
피드 공유하기 기능, // 아직 미정 메시지기능하면 개발예정
.
.
.
백엔드는 너무 할게많아 일단은 Entity 설계부터하고 기능 개발시 주제를 정해서 하나하나 적어보겠다.
뭐대략적인 계획은 이렇고
오늘은 react-native 프로잭트 생성후 네비게이터에대해 공부하면서 개발할예정이다.
시작하겠다.
#0. 추가적으로 사용한 모듈들
- expo
- yarn
- redux-toolkit
- styled-components
- react-navigtion
#1. expo 프로잭트 설치
expo 설치방법은 아래 포스팅해둔 글이있다 참고바란다.
2022.12.18 - [개발/react-native] - [REACT NATIVE] 프로젝트 시작하기
#2. 폴더 구조 잡기
일단 네비게이션 스크린 구조를 잡아보겠다.
기본적으로 src 안에 모든 폴더와 파일들이있다.
App.js는 따로 넣지않고 밖에다 두었다
그이유는 expo는 index.js 가없기떄문에
인식을 못하는것같다.
constants = 라우터, 각종 편리하게 뽑아쓸 모듈들 현재 라우터와 아이콘관련 코드들이 들어있다
navigations = 네비게이션들이 있는 폴더
screens = 이폴더안에 메인 스크린들이 있고 메인스크린에대한 토픽의 폴더가 하나더있다
그 폴더안에는 레이아웃 혹은 탭들이 들어갈것이다.
slicers = 리덕스를 사용하기위한 폴더
이정도 구조를 잡아보았다
초반에 바텀 네비게이션을 기준으로 만들었다가
바텀네비게이션은 그대로 있어야하는데 같이 슬라이드가 되는 불상사가일어나
처음부터 다시 작업을하였고
처음 네비게이션에는 로그인, 회원가입 , 바텀 네비게이션 = index
가 들어가있고
이 바텀네비게이션은
을 사용하여 이 바텀 네비게이션 안에 홈 찾기 마이페이지 등등 한번더 존재한다
자 시작해보자.
#3. 네비게이션 만들기
리엑트 네이티브 네비게이션을 사용하기위해선
몇가지 모듈을 다운로드해야한다.
// 리엑트 네이비게이션 사용시 필요한 모듈들
이 styled-components/native는 yarn으로 다운받자
npm으로 다운받으니 오류가 뜬다.
yaen add styled-components/native
yarn add @react-navigation/stack
yarn add @react-navigation/native
yarn add react-native-safe-area-view
yarn add react-native-safe-area-context
yarn add react-native-gesture-handler
yarn add react-native-elements
yarn add @expo/vector-icons
yaen add @react-navigation/bottom-tabs
or
npm install @react-navigation/stack
npm install @react-navigation/native
npm install react-native-safe-area-view
npm intall react-native-safe-area-context
npm intall react-native-gesture-handler
npm install react-native-elements
npm install @expo/vector-icons
npm install @react-navigation/bottom-tabs
- AuthNavigation.js
// src/navigations/AuthNavigation
import React from 'react'
import { StyleSheet, useColorScheme } from 'react-native'
import {createStackNavigator} from "@react-navigation/stack";
import {NavigationContainer} from "@react-navigation/native";
import BottomNavigation from "./BottomNavigation";
import LoginScreen from "../screens/auth/LoginScreen";
import RegisterScreen from "../screens/auth/RegisterScreen";
import ForgotPassword from "../screens/auth/ForgotPassword";
import { useSelector, useDispatch } from 'react-redux';
import themeSlicer from '../slicers/themeSlicer'
import {lightTheme, darkTheme} from '../../Theme'
import { ROUTES } from '../constants/routes';
import styled,{ThemeProvider} from 'styled-components'
const Stack = createStackNavigator();
const screenOption = {
headerShown: false,
}
const AuthNavigaition = () => {
const theme = useSelector((state) => state.themeSlicer.theme);
const dispatch = useDispatch();
const colorScheme = useColorScheme();
dispatch(themeSlicer.actions.changeTheme(colorScheme === 'dark' ? darkTheme : lightTheme))
return (
<ThemeProvider theme={theme}>
<NavigationContainer>
<Stack.Navigator initialRouteName={ROUTES.LOGIN} screenOptions={screenOption}>
<Stack.Screen name={ROUTES.LOGIN} component={LoginScreen}/>
<Stack.Screen name={ROUTES.REGISTER} component={RegisterScreen}/>
<Stack.Screen name={ROUTES.FORGOTPASSWORD} component={ForgotPassword}/>
<Stack.Screen name={ROUTES.INDEX} component={BottomNavigation}/>
</Stack.Navigator>
</NavigationContainer>
</ThemeProvider>
)
}
export default AuthNavigaition
const styles = StyleSheet.create({})
이 프로젝트의 주축이될 네비게이션이다.
첫 기본 화면은 로그인화면이고
이안에 바텀 네비게이션이있다.
또한 이 바텀 네비게이션안에는 여러가지 탭들이있다.
일단 네비게이션을 사용하기위해서는 NavigationContainer로 감싸줘야한다
그렇지않으면
이런 오류를 보게될것이다.
Error: Couldn't register the navigator. Have you wrapped your app with 'NavigationContainer'?
잘 감싸주도록 하자
AuthNavigation.js 를 만들었으니
App.js에 임포트 시켜주겠다.
그리고 기본 라우터인 HomeScreen에 SafeAreaVIew 를 사용해
모바일 상단과 하단의 안전한 여백을 주고
useColorScheme 를 사용해 동적으로
배경화면을 다크모드와 화이트모드시 배경색이 변경될수있도록 작업해주겠다.
+++++++++++++++++++++++ 추가++++++++++++++++++++++++++++++++++++++
expo로 개발하면 크롬 디버그를 자동으로 사용하게되는거같다
창피하지만... 본인은 이걸 끌줄을 모른다..
그래서 현재 useColorScheme 를 사용하면 계속 light만 return 될것이다.
일단은 이문제를 접어두고 dark모드 light모드 둘다 dark모드라고 임시적으로 통일해둔 상태이고
거기에 맞춰 UI를 제작하였다.
- App.js
// App.js
import {Provider} from "react-redux";
import store from "./store";
import AuthNavigaitor from './src/navigations/AuthNavigaiton'
import { SafeAreaView } from "react-native";
export default function App() {
return (
<Provider store={store}>
<AuthNavigaitor/>
</Provider>
);
}
네비게이션이 잘 동작하는걸 확인할수있다.
자 이제 본격적으로 BottomNavigation.js 를 만들고
AuthNavigation 안에 넣어주자
- BottomNavigation.js
// src/navigations/BottomNavigation.js
import {createBottomTabNavigator} from '@react-navigation/bottom-tabs'
import React from 'react'
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 "@expo/vector-icons/Ionicons";
import {BOTTOM_ICONS} from '../constants/icons';
import { useSelector } from 'react-redux';
const Tab = createBottomTabNavigator();
const BottomNavigation = () => {
const theme = useSelector((state) => state.themeSlicer.theme);
return (
<Tab.Navigator initialRouteName='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>
)
}
const Avatar = styled.Image`
width: 32px;
height: 32px;
border-radius: 50px;
border-width: 2px;
border-color: white;
`;
export default BottomNavigation
바텀네비게이션은 그대로 있고 나머지탭들이 잘 동작하는걸 볼수있다.
그리고또한 버튼을 클릭했을시 outline이 해제되고 꽉찬 것을 볼수있다.
이제 홈스크린을 만들어볼것이다.
바텀 네비게이션 가장 첫번째 홈 부분이다.
#3. 홈스크린 만들기
- HomeScreen.js
// src/screens/HomeScreen.js
import React from 'react'
import styled, { ThemeProvider } from "styled-components/native";
import { useDispatch, useSelector } from "react-redux"; // userDispatch = 데이터 변경시 사용 // useSelector = 데이터 가져올때 사용
import { darkTheme, lightTheme } from "../../Theme";
import themeSlicer from "../slicers/themeSlicer";
import Header from '../screens/home/Header'
import FeedList from './home/FeedList';
import StoryList from './home/StoryList';
const HomeScreen = ({ }) => {
const theme = useSelector((state) => state.themeSlicer.theme);
const dispatch = useDispatch();
return (
<SafeAreaView>
<Header />
<HomeScreenScrollView>
<StoryList></StoryList>
<FeedList></FeedList>
</HomeScreenScrollView>
</SafeAreaView>
)
}
export default HomeScreen
const HomeScreenScrollView = styled.ScrollView`
`;
const Text = styled.Text`
color: ${props => props.theme.TextColor};
`;
const SafeAreaView = styled.SafeAreaView`
flex: 1;
background-color: ${props => props.theme.backgroundColor};
`;
원래는 인스타그램을 캡처해 설명하려했지만
다른사람들 얼굴이 노출이되서 포기하였다.
일단 글로 최대한 설명하겠다.
<Header/> = 상단 인스타 그램 로고 부분이있는 헤더 부분이다.
<StoryList/> = 로고 아래있는 스토리리스트이고 <StoryList/> 안에는 <Story/> 가 존재한다. 실질적으로 저곳에서
코딩할것이다.
<FeedList/> = 사진과 좋아요 그리고 코멘트들이 들어있는 리스트이다 StoryList와 같이 내부에 <Feed/> 가 존재한다.
상단에 모든코드를 보여주고 마지막에 최종완성모습을 보여주겠다.
#3.1 홈스크린- Header.js 만들기
- Header.js
// src/screens/home/Header.js
import React from 'react'
import styled, { ThemeProvider } from "styled-components/native";
import { useDispatch, useSelector } from "react-redux"; // userDispatch = 데이터 변경시 사용 // useSelector = 데이터 가져올때 사용
import { darkTheme, lightTheme } from "../../../Theme";
import themeSlicer from "../../slicers/themeSlicer";
import Ionicons from "@expo/vector-icons/Ionicons";
import HeaderLogo from '../../../assets/header-logo.png'
import ICONS from '../../constants/icons'
const Header = ({ }) => {
const theme = useSelector((state) => state.themeSlicer.theme);
const dispatch = useDispatch();
return (
<Container>
<HeaderBox>
<TouchableOpacity>
<Image source={HeaderLogo} />
</TouchableOpacity>
<HeaderIconBox>
<TouchableOpacity>
<Ionicons name="add-circle-outline" size={28} color="white" />
</TouchableOpacity>
<TouchableOpacity>
<UnderDot />
<Ionicons name="heart-outline" size={28} color="white" />
</TouchableOpacity>
<TouchableOpacity>
<UnderRedIcon>
<UnderRedIconText>11</UnderRedIconText>
</UnderRedIcon>
<Ionicons name="paper-plane-outline" size={28} color="white" />
</TouchableOpacity>
</HeaderIconBox>
</HeaderBox>
</Container>
)
}
export default Header
const Text = styled.Text`
color: ${props => props.theme.TextColor};
`;
const Image = styled.Image`
width: 175px;
height: 51px;
`;
const TouchableOpacity = styled.TouchableOpacity`
margin-left: 15px;
`;
const Container = styled.View`
margin-right: 10px;
`;
const UnderDot = styled.View`
background-color: red;
position: absolute;
top: 0;
right: 0;
border-radius: 50px;
width: 10px;
height: 10px;
z-index: 100;
`;
const UnderRedIcon = styled.View`
background-color: red;
border-radius: 50px;
position: absolute;
align-items: center;
right: 0;
bottom: 20px;
padding: 5% 20%;
z-index: 100;
`;
const UnderRedIconText = styled.Text`
color: white;
font-weight: 600;
`;
const HeaderBox = styled.View`
flex-direction: row;
align-items: center;
justify-content: space-between;
`;
const HeaderIconBox = styled.View`
flex-direction: row;
align-items: center;
justify-content: space-between;
`;
const View = styled.View`
`;
#3.2 홈스크린- StoryList.js & Story.js 만들기
- StoryList.js
// src/screens/home/StoryList.js
import { View, Text } from 'react-native'
import React from 'react'
import styled from "styled-components/native";
import Story from './Story'
const StoryList = () => {
let list = [1,2,3,4,5,6,7,8];
return (
<StoryScrollView horizontal showsHorizontalScrollIndicator={false}>
{list.map((item, index) => {
return <Story index={index}/>
})}
</StoryScrollView>
)
}
const StoryScrollView = styled.ScrollView`
margin: 10px 10px;
`;
export default StoryList
- Story.js
// src/screens/home/Story.js
import React from 'react'
import styled from "styled-components/native";
const Story = ({ index }) => {
return (
<TouchableOpacity index={index}>
<Avatar source={{ uri: "https://i.ibb.co/ZhB1QPv/image.jpg" }} />
<Text>온석태</Text>
</TouchableOpacity>
)
}
const TouchableOpacity = styled.TouchableOpacity`
margin-right: 15px;
align-items: center;
`;
const Avatar = styled.Image`
width: 60px;
height: 60px;
border-radius: 50px;
border-width: 2px;
border-color: red;
`;
const Text = styled.Text`
color: ${props => props.theme.TextColor};
margin-top: 5px;
font-size: 13px;
`;
const View = styled.View`
`;
export default Story
#3.2 홈스크린- FeedList.js & Feed.js 만들기
- FeedList.js
// src/screen/home/FeedList.js
import { View, Text } from 'react-native'
import React from 'react'
import Feed from './Feed'
import styled from "styled-components/native";
const FeedList = () => {
let list = [1,2,3,4,5,6,7,8];
return (
<FeedScrollView>
{list.map((item, index) => {
return <Feed index={index}/>
})}
</FeedScrollView>
)
}
const FeedScrollView = styled.ScrollView`
`;
export default FeedList
- Feed.js
// src/screens/home/Feed.js
import React from 'react'
import styled from "styled-components/native";
import { useDispatch, useSelector } from "react-redux"; // userDispatch = 데이터 변경시 사용 // useSelector = 데이터 가져올때 사용
import { darkTheme, lightTheme } from "../../../Theme";
import themeSlicer from "../../slicers/themeSlicer";
import Ionicons from "@expo/vector-icons/Ionicons";
import HeaderLogo from '../../../assets/header-logo.png'
import { ICONS } from '../../constants/icons'
const FeedList = ({ index }) => {
const theme = useSelector((state) => state.themeSlicer.theme);
const dispatch = useDispatch();
return (
<Container index={index}>
<FeedHeader />
<FeedBody />
<FeedBottom />
</Container>
)
}
function iconMode() {
let color;
const theme = useSelector((state) => state.themeSlicer.theme);
return theme.mode === 'dark' ? 'white' : 'white'
}
const FeedHeader = () => {
return (
<HeaderBox>
<HeaderProfileBox>
<TouchableOpacity>
<Avatar source={{ uri: "https://i.ibb.co/ZhB1QPv/image.jpg" }} />
</TouchableOpacity>
<TouchableOpacity>
<Text>온석태</Text>
</TouchableOpacity>
</HeaderProfileBox>
<View>
<TouchableOpacity>
<Ionicons name="ellipsis-horizontal-outline" size={20} color={iconMode()}></Ionicons>
</TouchableOpacity>
</View>
</HeaderBox>
)
}
const FeedBody = () => {
return (
<View>
<View>
<Image source={{ uri: "https://editsay.s3.ap-northeast-2.amazonaws.com/images/%EB%8C%80%EC%A7%80+1_1-100.jpg" }} />
</View>
<FeedBodyBottom>
<FeedBodyBottomIconsFrontBox>
<FrontTouchableIcon name={ICONS.heartOutline} />
<FrontTouchableIcon name={ICONS.commentOutline} />
<FrontTouchableIcon name={ICONS.shareOutline} />
</FeedBodyBottomIconsFrontBox>
<View>
<TouchableIcon name={ICONS.horizontalThreeDots} />
</View>
<FeedBodyBottomIconsEndBox>
<TouchableIcon name={ICONS.saveOutline} />
</FeedBodyBottomIconsEndBox>
</FeedBodyBottom>
</View>
)
}
const FeedBottom = () => {
return (
<FeedBottomBox>
<FeedLikes />
<FeedCaption />
<FeedComments />
</FeedBottomBox>
)
}
const FeedLikes = () => {
return (
<View>
<LikesText>좋아요 353,165</LikesText>
</View>
)
}
const FeedCaption = () => {
return (
<CaptionBox>
<CaptionAuthorText>온석태</CaptionAuthorText>
<CaptionText>모두가 바라왔던 가장 가변운 요즘제 출시! 다운로드 없이 언제 어디서나 음악을 즐겨보세요</CaptionText>
</CaptionBox>
)
}
const FeedComments = () => {
return (
<CommentsBox>
<TouchableOpacity>
<CommentLengthText>댓글 3개 모두보기</CommentLengthText>
</TouchableOpacity>
<CommentBox>
<TouchableOpacity>
<CommentAuthorText>온석태</CommentAuthorText>
</TouchableOpacity>
<CommentText>너무 멋진 피드이네요!</CommentText>
</CommentBox>
</CommentsBox>
)
}
const FrontTouchableIcon = ({ name }) => {
return (
<FrontTouchableOpacity>
<Ionicons name={name} size={25} color={iconMode()}></Ionicons>
</FrontTouchableOpacity>
)
}
const TouchableIcon = ({ name }) => {
return (
<TouchableOpacity>
<Ionicons name={name} size={25} color={iconMode()}></Ionicons>
</TouchableOpacity>
)
}
export default FeedList
const Avatar = styled.Image`
width: 32px;
height: 32px;
border-radius: 50px;
border-width: 2px;
border-color: ${props => props.theme.TextColor};
margin-right: 10px;
`;
const CommentsBox = styled.View`
margin-top: 10px;
`;
const CommentLengthText = styled.Text`
color: ${props => props.theme.LigtherTextColor};
`;
const CommentAuthorText = styled.Text`
color: ${props => props.theme.TextColor};
font-weight: 600;
margin-right: 8px;
`;
const CommentText = styled.Text`
color: ${props => props.theme.TextColor};
font-weight: 300;
`;
const CommentBox = styled.View`
flex-direction: row;
margin-top: 10px;
`;
const CaptionBox = styled.View`
flex-direction: row;
margin-top: 10px;
`;
const CaptionAuthorText = styled.Text`
color: ${props => props.theme.TextColor};
font-weight: 600;
margin-right: 10px;
`;
const CaptionText = styled.Text`
color: ${props => props.theme.TextColor};
font-weight: 300;
`;
const FeedBottomBox = styled.View`
margin: 0px 10px;
`;
const LikesText = styled.Text`
color: ${props => props.theme.TextColor};
font-size: 13px;
`;
const Text = styled.Text`
color: ${props => props.theme.TextColor};
`;
const Image = styled.Image`
width: 100%;
height: 500px;
`;
const FrontTouchableOpacity = styled.TouchableOpacity`
margin-right: 10px;
`;
const TouchableOpacity = styled.TouchableOpacity`
`;
const FeedBodyBottomIconsFrontBox = styled.View`
flex-direction: row;
width: 40%;
`;
const FeedBodyBottomIconsEndBox = styled.View`
align-items: flex-end;
width: 40%;
`;
const FeedBodyBottom = styled.View`
margin: 20px 10px;
flex-direction: row;
justify-content: space-between;
align-items: center;
`;
const HeaderBox = styled.View`
margin: 10px;
flex-direction: row;
justify-content: space-between;
align-items: center;
`;
const HeaderProfileBox = styled.View`
flex-direction: row;
align-items: center;
`;
const View = styled.View`
`;
const ScrollView = styled.ScrollView`
`;
const Container = styled.View`
margin-bottom: 50px;
`;
여기까지 만들었으면 끝이난것이다.
이것이 결과 화면이다.
이렇게 모든 작업이 끝이났다
다음시간에는 로그인쪽과 가입쪽을 구현하도록 하겠다.
참고로 styled-icon 이라는 모듈이있는데
react-native 와 연동이 되지않는다고 한다.
이것때문에 고생하지말고 react 백터 아이콘을 쓰도록 하자
또한 아래 깃허브가있으니 보고싶은사람은 와서 봐도 된다.
다만 아직 완성된것이아니기때문에 수시로 푸시가 들어가 동작을 안할수있으니 참고바란다.
https://github.com/1domybest/react-native-ig-clone.git
다음글 >
'개발 > react-native' 카테고리의 다른 글
[REACT NATIVE] 리엑트 네이티브 인스타그램 클론 코딩 (2) Formik + yub 을 사용하여 인스타 그램 로그인폼 구현하기 -git 참조- (0) | 2022.12.25 |
---|---|
[REACT-NATIVE] Redux Toolkit 과 Styled Components를 사용하여 자동 다크모드 라이트모드 구현하기 (2) | 2022.12.23 |
[REDUX] Redux Toolkit 사용해보기 + 로그인 버튼 Client 단부터 reducer 까지 -git첨부- (0) | 2022.12.21 |
[REACT NATIVE] Redux-Saga 프로젝트 시작하기 -git첨부- (0) | 2022.12.21 |
[REACT NATIVE] IMMER 사용하기 + REDUX 추가설명 -git첨부- (0) | 2022.12.20 |