Carpool(React Native & Express & apollo federation & Mariadb, Mongodb) - 3. 로그인, 회원가입 화면

#1 로그인 화면

로그인 화면 UI를 작성하기 이전에 공통으로 사용될 컴포넌트들을 만들어 보도록 하겠습니다.

  • ./src/screens/common/BorderButton.js
import React from 'react';
import { Text, TouchableOpacity } from 'react-native';
import styles from './styles/styled.border.button';

const BorderButton = ({
    text,
    onPress
}) => {
    return(
        <TouchableOpacity style={ styles.button }
                          onPress={ onPress }
        >
            <Text style={ styles.text }>{ text }</Text>
        </TouchableOpacity>
    );
};

export default BorderButton;
  • ./src/screens/common/styles/styled.border.button.js
import { StyleSheet } from "react-native";
import palette from "../../../utils/palette";

const styles = StyleSheet.create({
    button: {
        width: 300,
        height: 40,
        borderRadius: 30,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: palette.white[0],
        borderColor: palette.red[4],
        borderWidth: 2,
        margin: 10,
    },
    text: {
        fontSize: 15,
        color: palette.red[4],
    }
});

export default styles;
  • ./src/screens/common/FullButton.js
import React from 'react';
import { Text, TouchableOpacity } from 'react-native';
import styles from './styles/styled.full.button';

const FullButton = ({
    onPress,
    text
}) => {
    return(
        <TouchableOpacity style={ styles.button }
                          onPress={ onPress }
        >
            <Text style={ styles.text }>
                { text }
            </Text>
        </TouchableOpacity>
    );
};

export default FullButton;
  • ./src/screens/common/styles/styled.full.button.js
import { StyleSheet } from "react-native";
import palette from "../../../utils/palette";

const styles = StyleSheet.create({
    button: {
        width: 300,
        height: 40,
        borderRadius: 30,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: palette.red[4],
        margin: 10,
    },
    text: {
        fontSize: 15,
        color: palette.white[0],
    },
});

export default styles;
  • ./src/screens/common/BottomlineInput.js
import React from 'react';
import { TextInput } from 'react-native';
import styles from './styles/styled.bottomline.input';

const BottomlineInput = ({
    inputAccessoryViewID,
    placeholder,
    placeholderTextColor,
    onChange,
    value
}) => {
    return <TextInput style={ styles.input }
                      inputAccessoryViewID={ inputAccessoryViewID }
                      placeholder={ placeholder }
                      placeholderTextColor={ placeholderTextColor }
                      onChange={ onChange }
                      value={ value }
           />;
};

export default BottomlineInput;
  • ./src/screens/common/styles/bottomline.input.js
import { StyleSheet } from "react-native";
import palette from "../../../utils/palette";

const styles = StyleSheet.create({
    input: {
        width: 300,
        height: 40,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: palette.white[0],
        borderBottomColor: palette.red[3],
        borderBottomWidth: 1,
        fontSize: 15,
        margin: 10,
    },
});

export default styles;

앞으로 사용할 공통 버튼, 인풋 컴포넌트를 작성했습니다. 그러면 이 컴포넌트들을 가지고 로그인화면을 작성해보도록 하겠습니다.

위의 화면을 토대로 작성을 진행하겠습니다.

  • ./src/screens/auth/components/LoginForm.js
import React from 'react';
import { CommonActions, useNavigation } from '@react-navigation/native';
import { View } from 'react-native';
import palette from '../../../utils/palette';
import FullButton from '../../../common/FullButton';
import BorderButton from '../../../common/BorderButton';
import BottomlineInput from '../../../common/BottomlineInput';
import styles from '../../../common/styles/styled.form';

const LoginForm = () => {
    const navigation = useNavigation();
    const toMainNav = e => {
        navigation.dispatch(CommonActions.reset({
            routes: [{ name: 'bottom-nav' }]
        }));
    };
    const toSignup = e => {
        navigation.navigate('signup');
    };

    return (
        <View style={ styles.box }>
            <BottomlineInput inputAccessoryViewID="email"
                             placeholder="E-mail"
                             placeholderTextColor={ palette.gray[4] }
            />
            <BottomlineInput inputAccessoryViewID="password"
                             placeholder="Password"
                             placeholderTextColor={ palette.gray[4] }
            />
            <FullButton text="Signin"
                        onPress={ toMainNav }
            />
            <BorderButton text="Signup"
                          onPress={ toSignup }
            />
        </View>
    );
};

export default LoginForm;
  • ./src/screens/auth/LoginScreen.js
import React from 'react';
import { View } from 'react-native';
import LoginForm from './components/LoginForm';
import styles from '../common/styles/styled.screen';

const LoginScreen = () => {
    return(
        <View style={ styles.container }>
            <LoginForm />
        </View>
    );
};

export default LoginScreen;

로그인 컴포넌트를 완성했습니다. 이어서 회원가입 화면을 구현하도록 하겠습니다.

#2 회원가입 화면

위의 화면을 토대로 회원가입 화면을 작성하기 이전에 회원가입 상단 문구 컴포넌트를 작성하도록 하겠습니다.

  • ./src/screens/auth/components/InformationText.js
import React from 'react';
import { Text, View } from 'react-native';
import styles from '../styles/information.text';

const InformationText = ({ text }) => {
    return (
        <View style={ styles.location }>
            <Text style={ styles.text }>
                { text }
            </Text>
        </View>
    );
};

export default InformationText;
  • ./src/screens/auth/styles/information.text.js
import { StyleSheet } from "react-native";

const styles = StyleSheet.create({
    location: {
        justifyContent: 'flex-start',
        alignItems: 'flex-start',
        marginBottom: 20,
        width: 300
    },
    text: {
        fontSize: 18,
    }
});

export default styles;

문구를 작성했으니 회원가입 폼을 작성하도록 하겠습니다.

  • ./src/screens/auth/components/RegisterForm.js
import { useNavigation } from '@react-navigation/core';
import React from 'react';
import { View } from 'react-native';
import BottomlineInput from '../../common/BottomlineInput';
import palette from '../../../utils/palette';
import styles from '../../common/styles/styled.form';
import FullButton from '../../common/FullButton';
import InformationText from './InformationText';

const RegisterForm = () => {
    const navigation = useNavigation();
    const toLicenseScreen = e => {
        navigation.navigate('license');
    };

    return(
        <View style={ styles.box }>
            <InformationText text={ "회원가입을 위한 \n기본정보를 입력해주세요!" }/>
            <BottomlineInput inputAccessoryViewID="email"
                             placeholder="E-mail"
                             placeholderTextColor={ palette.gray[5] }
            />
            <BottomlineInput inputAccessoryViewID="password"
                             placeholder="Password"
                             placeholderTextColor={ palette.gray[5] }
            />
            <BottomlineInput inputAccessoryViewID="passwordConfirm"
                             placeholder="Re-password"
                             placeholderTextColor={ palette.gray[5] }
            />
            <BottomlineInput inputAccessoryViewID="nickname"
                             placeholder="Nickname"
                             placeholderTextColor={ palette.gray[5] }
            />
            <FullButton text="Next" 
                        onPress={ toLicenseScreen }
            />
        </View>
    );
};

export default RegisterForm;
  • ./src/screens/RegisterScreen.js
import React from 'react';
import { View } from 'react-native';
import RegisterForm from './components/RegisterForm';
import styles from '../common/styles/styled.screen';

const RegisterScreen = () => {
    return(
        <View style={ styles.container }>
            <RegisterForm />
        </View>
    );
};

export default RegisterScreen;

이 부분까지는 기본 회원 가입에 필요한 내용이고 이 후에 작성될 컴포넌트는 운전자 등록을 할 경우 필요한 컴포넌트입니다.

  • ./src/screens/components/LicenseForm.js
import React from 'react';
import { View } from 'react-native';
import BottomlineInput from '../../../common/BottomlineInput';
import styles from '../../../common/styles/styled.form';
import FullButton from '../../../common/FullButton';
import InformationText from './InformationText';
import { CommonActions } from '@react-navigation/native';
import { useNavigation } from '@react-navigation/native';
import palette from '../../../utils/palette';

const LicenseForm = () => {
    const navigation = useNavigation();
    const toSigninScreen = e => {
        navigation.dispatch(CommonActions.reset({
            routes: [{ name: 'signin' }]
        }));
    };

    return (
        <View style={ styles.box }>
            <InformationText text={ "운전자 등록 화면입니다. \n등록을 하시려면 사항들을 기입해주세요. \n미등록의 경우 가입 버튼을 눌러주세요!" } />
            <BottomlineInput inputAccessoryViewID="birthDate"
                             placeholder="Birth Date"
                             placeholderTextColor={ palette.gray[5] }
            />
            <BottomlineInput inputAccessoryViewID="name"
                             placeholder="Name"
                             placeholderTextColor={ palette.gray[5] }
            />
            <BottomlineInput inputAccessoryViewID="licNumber"
                             placeholder="License Number"
                             placeholderTextColor={ palette.gray[5] }
            />
            <FullButton text="Signup" 
                        onPress={ toSigninScreen }
            />
        </View>
    );
};

export default LicenseForm;
  • ./src/screens/auth/LicenseScreen.js
import React from 'react';
import { View } from 'react-native';
import styles from '../../common/styles/styled.screen';
import LicenseForm from '../auth/components/LicenseForm';

const LicenseScreen = () => {
    return (
        <View style={ styles.container }>
            <LicenseForm />
        </View>
    );
};

export default LicenseScreen;

#3 네비게이션 추가 및 테스트

로그인, 회원가입 관련 페이지를 첫 화면으로 설정하기 위해 MainNavigator에 컴포넌트를 추가하도록 하겠습니다.

  • ./src/navigator/MainNavigator.js
import React from "react";
import { createStackNavigator } from '@react-navigation/stack';
import { NavigationContainer } from "@react-navigation/native";
import LoginScreen from '../screens/auth/LoginScreen';
import RegisterScreen from '../screens/auth/RegisterScreen';
import LicenseScreen from '../screens/auth/LicenseScreen';
import BottomNavigator from "./BottomNavigator";

const Stack = createStackNavigator();
const MainNavigator = () => {
    return(
        <NavigationContainer>
            <Stack.Navigator>
                <Stack.Screen name="signin"
                              component={ LoginScreen }
                              options={{ headerShown: false }}
                />
                <Stack.Screen name="signup" 
                              component={ RegisterScreen }
                />
                <Stack.Screen name="license"
                              component={ LicenseScreen }
                />
                <Stack.Screen name="bottom-nav"
                              component={ BottomNavigator }
                              options={{ headerShown: false }}
                />
            </Stack.Navigator>
        </NavigationContainer>
    );
};

export default MainNavigator;

MainNavigator에 앞서 작성한 스크린들을 추가했으니 테스트를 진행해보도록 하겠습니다.



테스트 결과 화면이 잘 나오는 모습을 볼 수 있습니다. 다음 포스트에서는 백엔드 auth-service를 작성하도록 하겠습니다.

좋은 웹페이지 즐겨찾기