개발 일기
React native 로그인 화면 구현하기 #1 본문
1. Page 구성
우선 나는 로그인 화면을 먼저 구현해서 로그인이 됐다면 Todolist를 작성할 수 있게 만들었다.
그러기 위해 우선 navigation을 설치해줘야 한다.
npm install @react-navigation/native
npm install @react-navigation/native-stack
설치 후에 모바일 하단에 네비게이션 메뉴를 만들기 위해 추가로 설치해주자.
npm install @react-navigation/bottom-tabs
npm install @expo/vector-icons
bottom-tabs는 모바일 하단에 아이콘을 넣어 클릭시 페이지로 이동이 가능하게 해준다.
우선 설치 후에 만든 화면 구성을 먼저 살펴보자.
하단을 보면 MY PAGE와 TODO LIST가 보인다.
방금 설치한 bottom-tabs을 이용해 만들었다.
이제 다음은 firebase를 활용해 로그인, 회원가입 시 MY PAGE로 이동 하기를 구현해보자.
Login.jsx
import { StatusBar } from "expo-status-bar";
import {
SafeAreaView,
StyleSheet,
Text,
TextInput,
TouchableOpacity,
View,
Image,
} from "react-native";
import { useState } from "react";
import { authService } from "../firebase";
import {
createUserWithEmailAndPassword,
signInWithEmailAndPassword,
} from "firebase/auth";
import { updateProfile } from "firebase/auth";
import React from "react";
export default function Login() {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [displayName, setDisplayName] = useState("");
const [newAccount, setNewAccount] = useState();
const toggleAccount = () => {
setNewAccount((prev) => !prev);
};
const SignUp = () => {
if (newAccount) {
createUserWithEmailAndPassword(authService, email, password)
.then(() => {
updateProfile(authService.currentUser, {
displayName: displayName,
});
})
.catch((error) => alert(error.message));
setEmail("");
setPassword("");
setDisplayName("");
} else {
signInWithEmailAndPassword(authService, email, password).catch((error) =>
alert(error.message)
);
console.log(authService);
setEmail("");
setPassword("");
}
};
return (
<SafeAreaView style={styles.safearea}>
<View style={styles.container}>
<View style={styles.imageview}>
<Image
source={require("../assets/todologo.png")}
style={styles.logoimage}
/>
</View>
<View style={styles.inputWrapper}>
{newAccount ? (
<TextInput
placeholder="User NickName"
style={styles.input}
autoCapitalize="none"
value={displayName}
onChangeText={(text) => setDisplayName(text)}
autoCorrect={false}
/>
) : null}
<TextInput
placeholder="User Email"
style={styles.input}
autoCapitalize="none"
value={email}
onChangeText={(text) => setEmail(text)}
autoCorrect={false}
/>
<TextInput
autoCapitalize="none"
autoCorrect={false}
secureTextEntry={true}
value={password}
onChangeText={(text) => setPassword(text)}
textContentType="password"
placeholder="User Password"
style={styles.input}
/>
</View>
<View style={styles.imageview}></View>
<View style={styles.tabview}>
<TouchableOpacity style={styles.tab} onPress={SignUp}>
<Text style={styles.tabText}>
{newAccount ? "회원가입" : "로그인"}
</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.tab}>
<Text style={styles.tabText}>Google</Text>
</TouchableOpacity>
</View>
<View>
<TouchableOpacity style={styles.tab2} onPress={toggleAccount}>
<Text style={styles.tabText2}>
{newAccount ? "로그인 하시겠습니까?" : "회원가입 하시겠습니까?"}
</Text>
</TouchableOpacity>
</View>
</View>
<StatusBar
barStyle="dark-content"
backgroundColor={"transparent"}
translucent={true}
/>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
safearea: {
flex: 1,
},
container: {
flex: 1,
paddingVertical: 30,
paddingHorizontal: 20,
backgroundColor: "white",
},
header: {
marginTop: 10,
fontSize: 50,
textAlign: "center",
},
imageview: {
flexDirection: "row",
},
logoimage: {
alignItems: "center",
marginLeft: "auto",
marginRight: "auto",
},
inputWrapper: {
paddingVertical: 15,
marginTop: 30,
marginBottom: 30,
borderTopWidth: 1,
borderBottomWidth: 1,
paddingVertical: 15,
},
input: {
borderWidth: 1,
paddingVertical: 10,
paddingHorizontal: 20,
margin: 5,
},
tabview: {
flexDirection: "row",
},
tab: {
marginTop: 30,
backgroundColor: "black",
paddingHorizontal: 10,
paddingVertical: 15,
width: "30%",
alignItems: "center",
borderRadius: 50,
margin: 37,
},
tab2: {
marginTop: 20,
borderColor: "black",
borderWidth: 2,
paddingHorizontal: 10,
paddingVertical: 15,
width: "100%",
alignItems: "center",
borderRadius: 50,
},
tabText: {
fontWeight: "600",
fontSize: 17,
color: "white",
},
tabText2: {
fontWeight: "600",
fontSize: 20,
color: "black",
},
});
SignUp을 통해 회원가입과 로그인을 구현했다.
firebase에서 닉네임을 설정해주기 위해서는 updateprofile이 필요하다.
물론 이 부분도 firebase를 먼저 설치해주고 firebase.js 파일에 키 값을 넣어줘야 구현이 가능하다.
toggleAccount는 한 페이지에서 버튼을 클릭시 회원가입 화면과 로그인 화면을 나눠주는 기능을 해준다.
전 프로젝트에서 사용했는데 너무 유용해서 넣어봤다.
참고로 리액트 네이티브에서는 onClick 대신에 onPress 기능을 사용한다.
이제 구현한 로그인 화면을 확인해보자.
화면을 확인해보면 토글 버튼도 이상없이 동작하고 로그인시 firebase에도 데이터가 이상없이 들어간다.
로그인을 확인하면 로그인 or 회원가입 탭이 메인페이지와 투두리스트 탭으로 바뀌는 것을 볼 수 있는데 이 부분을 구현해보자.
<App.js>
import React from "react";
import { NavigationContainer } from "@react-navigation/native";
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";
import Login from "./Pages/Login";
import TodoList from "./Pages/TodoList";
import Profile from "./Pages/Profile";
import { FontAwesome } from "@expo/vector-icons";
import "react-native-get-random-values";
import { useState } from "react";
import { authService } from "./firebase";
import { useEffect } from "react";
const BottomTab = createBottomTabNavigator();
export default function App() {
const [isLoggedIn, setIsLoggedIn] = useState(authService.currentUser);
useEffect(() => {
authService.onAuthStateChanged((user) => {
if (user) {
setIsLoggedIn(true);
} else {
setIsLoggedIn(false);
}
});
});
return (
<NavigationContainer>
<BottomTab.Navigator>
{isLoggedIn ? (
<BottomTab.Screen
name="MY PAGE"
component={Profile}
options={{
headerShown: false,
headerTitleStyle: {
fontSize: 25,
fontWeight: "bold",
color: "black",
marginLeft: 150,
},
tabBarActiveTintColor: "black",
tabBarLabelStyle: { fontSize: 15 },
tabBarIcon: () => (
<FontAwesome name="user" size={20} color={"black"} />
),
}}
/>
) : (
<BottomTab.Screen
name="로그인 or 회원가입"
component={Login}
options={{
headerShown: false,
headerTitleStyle: {
fontSize: 25,
fontWeight: "bold",
color: "black",
marginLeft: 150,
},
tabBarActiveTintColor: "black",
tabBarLabelStyle: { fontSize: 15 },
tabBarIcon: () => (
<FontAwesome name="user" size={20} color={"black"} />
),
}}
/>
)}
{isLoggedIn ? (
<BottomTab.Screen
name="TODO LIST"
component={TodoList}
options={{
headerShown: false,
headerTitleStyle: {
fontSize: 25,
fontWeight: "bold",
color: "black",
marginLeft: 140,
},
tabBarActiveTintColor: "black",
tabBarLabelStyle: { fontSize: 15 },
tabBarIcon: () => (
<FontAwesome name="pencil" size={20} color={"balck"} />
),
}}
/>
) : null}
</BottomTab.Navigator>
</NavigationContainer>
);
}
isloggedin을 활용해서 firebase auth 서버를 이용해 user 여부로 true와 false를 나눴고,
BottomTab.Navigator에 삼항연산자를 만들었다.
TODO LIST 페이지는 만약 user가 없다면 null 값을 보이게 만들어주면 초기 로그인 화면에는 아무 화면도 보이지 않는다.
이제 다음은 로그인시 보이는 MY PAGE와 TODO LIST를 만들어보자.
'React native' 카테고리의 다른 글
FlatList 사용 방법 (0) | 2023.01.05 |
---|---|
expo 프로젝트 생성 및 navigation (0) | 2023.01.04 |
React native firebase id 오류 (0) | 2023.01.03 |
React native Todo list 구현하기 #2 (0) | 2023.01.02 |
React native 시작하기 (0) | 2022.12.30 |