기본셋팅 및 버전
- Visual Studio Code v1.63.2
- nodeJS 14.16
- expo 5.0.1
- react-native 0.66.4
- firebase 9.6.2
- expo 44.0.4
- @react-navigation/native 6.0.6
- @react-navigation/native-stack 6.2.5
- react-native-safe-area-context
- formik 2.2.9
- yup 0.32.11
- email-validator 2.0.4
나머지 라이브러리들은 쓰면서 추가하겠습니다.
이어서 Login 및 Signup 페이지 를 제작해 보겠습니다.
Signup.js
import React from 'react'
import { View, Text, StyleSheet, TextInput, TouchableOpacity, Pressable, Image } from 'react-native'
import { getAuth, createUserWithEmailAndPassword } from 'firebase/auth'
import { getFirestore, doc, setDoc } from 'firebase/firestore'
import { Formik } from 'formik';
import * as Yup from 'yup'
const Signup = ({ navigation }) => {
const signUpFormSchema = Yup.object().shape({
email: Yup.string().email().required('정확한 이메일형식으로 작성해주세요'),
password: Yup.string().required().min(6, '비밀번호 6자리 이상 입력하세요'),
name: Yup.string().required().min(2, '적합하지않은 이름입니다.')
})
const db = getFirestore();
const auth = getAuth();
const onSignUp = (email, password, name) => {
try {
// console.log(email, password, name)
createUserWithEmailAndPassword(auth, email, password)
.then((result) => {
setDoc(doc(db, 'users', auth.currentUser.uid), { email, name })
})
} catch (error) {
console.log(error.message)
}
}
return (
<View style={styles.container}>
<Image style={styles.logo} source={require(`../../assets/instagramlogo.png`)} />
<View style={styles.formik}>
<Formik
initialValues={{ email: '', password:'', name: '' }}
onSubmit={values => onSignUp(values.email, values.password, values.name)}
validationSchema={signUpFormSchema}
validateOnMount={true}
>
{({ handleChange, handleBlur, handleSubmit, values, isValid }) => (
<>
<View >
<TextInput
style={styles.inputs}
placeholder='이메일'
autoCorrect={false} // 자동수정 비활성화
autoFocus={true} // 페이지오픈시 포커스
autoCapitalize='none'
textContentType='emailAddress'
onChangeText={handleChange('email')}
onBlur={handleBlur('email')}
value={values.email}
/>
</View>
<View>
<TextInput
style={styles.inputs}
placeholder='비밀번호'
autoCorrect={false}
secureTextEntry={true} // 비밀번호 *** 처리
autoCapitalize='none'
textContentType='password'
onChangeText={handleChange('password')}
onBlur={handleBlur('password')}
value={values.password}
/>
</View>
<View>
<TextInput
style={styles.inputs}
placeholder='이름'
autoCorrect={false}
autoCapitalize='none'
textContentType='text'
onChangeText={handleChange('name')}
onBlur={handleBlur('name')}
value={values.name}
/>
</View>
<Pressable style={[styles.signupbtn,{ backgroundColor: isValid ? '#6BB0F5' : '#9ACAF7', }]} onPress={handleSubmit}>
<Text style={styles.signupbtnText}>회원가입</Text>
</Pressable>
</>
)}
</Formik>
</View>
<TouchableOpacity style={[styles.moveContainer, styles.loginBtn]} onPress={() => navigation.goBack()}>
<Text style={[styles.moveText]}>이미 계정이 있으신가요?</Text>
<Text style={[styles.moveText, styles.moveTextBold]}>로그인하기</Text>
</TouchableOpacity>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: 'white'
},
logo: {
width: 160,
height: 45,
marginBottom: 30
},
formik:{
width:'100%',
paddingHorizontal:'5%'
},
inputs: {
backgroundColor: 'whitesmoke',
padding: 10,
borderWidth: 1,
borderColor: 'gainsboro',
borderRadius: 5,
marginBottom: 15,
fontSize: '.7rem',
outlineStyle: 'none'
},
signupbtn: {
width: '100%',
height: 40,
backgroundColor: '#99c4e9',
borderRadius: 5,
alignItems: 'center',
justifyContent: 'center',
},
signupbtnText: {
color: 'white',
fontSize: '.7rem',
},
moveContainer: { flexDirection: 'row' },
moveText: { fontSize: '.6rem' },
moveTextBold: { fontWeight: '600' },
helpBtn: { marginVertical: 10 },
loginBtn: {
position: 'fixed',
bottom: 0,
left: 0, right: 0,
justifyContent: 'center',
alignItems: 'center',
height: 40,
borderTopWidth: 2,
borderTopColor: 'whitesmoke'
}
});
export default Signup
시그업 하는데 두가지의 방법을 확인하였습니다.
Formik으로 값확인하고 Yup으로 유효성검사를 하는 법
react의 useState를 활용하여 인풋값을 onChangeText로 setState 가져와서 submit할 때
유효성검사 하는법
npm 인스톨 수 보니 Formik도 사람들이 많이 쓰는거 같아서 Formik방법을 채택하였다.
Login.js
import { Pressable, Image, StyleSheet, TextInput, View, Text, TouchableOpacity } from 'react-native';
import { Formik } from 'formik';
import * as Yup from 'yup'
import { getAuth, signInWithEmailAndPassword } from 'firebase/auth';
const Login = ({ navigation }) => {
const auth = getAuth()
const signInFormSchema = Yup.object().shape({
email: Yup.string().email().required(''),
password: Yup.string().required().min(6, '')
})
const onSignIn = (email, password) => {
signInWithEmailAndPassword(auth, email, password)
.then()
.catch(err => {console.log('이메일 혹은 패스워드 확인 부탁드립니다.')})
}
return (
<View style={styles.container}>
<Image style={styles.logo} source={require(`../../assets/instagramlogo.png`)} />
<View style={styles.formik}>
<Formik
initialValues={{ email: '', password: '' }}
onSubmit={values => onSignIn(values.email, values.password)}
validationSchema={signInFormSchema}
validateOnMount={true}
>
{({ handleChange, handleBlur, handleSubmit, values, isValid }) => (
<>
<View >
<TextInput
style={styles.inputs}
placeholder='이메일'
autoCorrect={false} // 자동수정 비활성화
autoFocus={true} // 페이지오픈시 포커스
autoCapitalize='none'
textContentType='emailAddress'
onChangeText={handleChange('email')}
onBlur={handleBlur('email')}
value={values.email}
/>
</View>
<View>
<TextInput
style={styles.inputs}
placeholder='비밀번호'
autoCorrect={false}
autoCapitalize='none'
textContentType='password'
secureTextEntry={true}
onChangeText={handleChange('password')}
onBlur={handleBlur('password')}
value={values.password}
/>
</View>
<Pressable style={[styles.loginbtn, { backgroundColor: isValid ? '#6BB0F5' : '#9ACAF7', }]} onPress={handleSubmit} disabled={!isValid}>
<Text style={styles.loginbtnText}>로그인</Text>
</Pressable>
</>
)}
</Formik>
</View>
<TouchableOpacity onPress={() => console.log('fortget-passward')} style={[styles.moveContainer, styles.helpBtn]}>
<Text style={[styles.moveText]}>로그인 상세 정보를 잊으셨나요?</Text>
<Text style={[styles.moveText, styles.moveTextBold]}>로그인 도움말 보기.</Text>
</TouchableOpacity>
<TouchableOpacity style={[styles.moveContainer, styles.signupBtn]} onPress={() => navigation.navigate('Signup')}>
<Text style={[styles.moveText]}>계정이 없으신가요?</Text>
<Text style={[styles.moveText, styles.moveTextBold]}>가입하기</Text>
</TouchableOpacity>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
paddingHorizontal: '5%',
backgroundColor: 'white'
},
logo: {
width: 160,
height: 45,
marginBottom: 30
},
formik:{
width:'100%',
paddingHorizontal:'5%'
},
inputs: {
backgroundColor: 'whitesmoke',
padding: 10,
borderWidth: 1,
borderColor: 'gainsboro',
borderRadius: 5,
marginBottom: 15,
fontSize: '.7rem',
outlineStyle: 'none'
},
loginbtn: {
width: '100%',
height: 40,
backgroundColor: '#99c4e9',
borderRadius: 5,
alignItems: 'center',
justifyContent: 'center',
},
loginbtnText: {
color: 'white',
fontSize: '.7rem',
},
moveContainer: { flexDirection: 'row' },
moveText: { fontSize: '.6rem' },
moveTextBold: { fontWeight: '600' },
helpBtn: { marginVertical: 10 },
signupBtn: {
position: 'fixed',
bottom: 0,
left: 0, right: 0,
justifyContent: 'center',
alignItems: 'center',
height: 40,
borderTopWidth: 2,
borderTopColor: 'whitesmoke'
}
});
export default Login
이렇게 되면 잘 들어온다.
그럼 이제 엡 오픈 시 로그인되었는지 확인 후 메인페이지로 이동하는 엡으로 이동해야지요.
App.js
import { useEffect, useState } from 'react'
import { Text, View, TouchableOpacity, StyleSheet } from 'react-native';
import AuthScreen from './screens/AuthScreen';
import MainScreen from './screens/MainScreen'
import { initializeApp, getApps } from "firebase/app";
import { getAuth, onAuthStateChanged } from 'firebase/auth'
const firebaseConfig = {
apiKey: "yuor code",
authDomain: "yuor code",
projectId: "yuor code",
storageBucket: "yuor code",
messagingSenderId: "yuor code",
appId: "yuor code",
measurementId: "yuor code"
};
getApps.length === 0 ? initializeApp(firebaseConfig) : '';
export default function App() {
const [currentUser, setCurrentUser] = useState(null)
const useHandler = user => user ? setCurrentUser(user) : setCurrentUser(null)
useEffect(() => {
const auth = getAuth();
onAuthStateChanged(auth, (user) => useHandler(user))
}, [])
return (
<View style={styles.container}>
{ currentUser? <MainScreen />:<AuthScreen /> }
</View>
)
}
const styles = StyleSheet.create({
container: {
flex: 1
}
})
useEffect로 엡이 구동 될 때 firebase 에 로그인되어있는지 확인하고 아니면 로그인화면으로 이동하게 합니다.
( 먼처 로그인화면으로 이동했다가 갑자기 메인화면으로 넘어가는 현상이 있던데... 흐흠)
간략하게 메인페이지는 이렇게 구현하였다.
MainScreen.js
import React from 'react'
import { View, Text, TouchableOpacity } from 'react-native'
import { getAuth, signOut } from 'firebase/auth'
const MainScreen = () => {
const signOutBtn = () =>{
signOut(getAuth())
}
return (
<View>
<Text>{ getAuth().currentUser.uid }</Text>
<TouchableOpacity onPress={signOutBtn}>
<Text>logout</Text>
</TouchableOpacity>
</View>
)
}
export default MainScreen
이제 메인스크린을 작성해보자 이건 03으로 넘어갑니다.
'인스타그램클론코딩' 카테고리의 다른 글
인스타그램클론코딩(react-native, firebase, expo, Formik, Yup) 01 (0) | 2022.01.11 |
---|