본문 바로가기
프로그래밍/REACT-NATIVE

REACT-NATIVE(EXPO) SNS 프로젝트 시작 (4)

by Lihano 2021. 7. 25.
반응형

노마드 강의를 끝낸 후 직접 만들려다보니 엄청난 오류를 맞이했다🤣🤣

 

나는 전에 만들어뒀던 firebase 프로젝트에 지금 만들려고하는 웹앱도 연동시켜 같은 웹과 같은 서비스를 공유하도록 할 생각이었다.

 

문제는 내가 firebase auth에 설정한 도메인 제한 설정때문에 expo로 Auth 서비스를 사용할 수 없다.

Expo는 기본적으로 도메인이 없기 때문에 내가 설정한 도메인 필터에 자동으로 걸러진다.

 

이 문제를 해결하기 위해 고군분투했지만 우선은 다른 과제부터 해결하기로 했다.

그 중 하나가 React-navigation의 사용이다.

 

❓ 이게 뭐냐고 하면 기존 React 프레임워크에서 Router 역할과 비슷한 역할을 수행한다고 보면 된다.

굉장히 간단할 것 같지만 부끄럽게도 이것도 구현하는 데 굉장히 많은 오류를 경험했다.

 

먼저 위의 네비게이션을 적용하기 위한 로그인과 회원가입 폼을 만들어보자.

import React from "react";
import {
  View,
  Text,
  StyleSheet,
  TouchableOpacity,
  TextInput,
  Button,
} from "react-native";
import Firebase from "../firebase";

class Login extends React.Component {
  state = {
    email: ``,
    password: ``,
  };

  render() {
    return (
      <View style={styles.container}>
        <TextInput
          style={styles.inputBox}
          value={this.state.email}
          placeholder="Email"
          onChangeText={(email) => this.setState({ email })}
          autoCapitalize="none"
        />
        <TextInput
          style={styles.inputBox}
          value={this.state.password}
          placeholder="Password"
          onChangeText={(password) => this.setState({ password })}
          secureTextEntry={true}
          autoCapitalize="none"
        />
        <TouchableOpacity style={styles.button} onPress={this.handleLogin}>
          <Text style={styles.buttonText}>Login</Text>
        </TouchableOpacity>
        <Button title="Don't have an account yet? Sign up" />
      </View>
    );
  }
}

export default Login;

✔ Login.js

import React from "react";
import {
  View,
  Text,
  TextInput,
  TouchableOpacity,
  StyleSheet,
} from "react-native";
import Firebase from "../firebase";

class Signup extends React.Component {
  state = {
    name: "",
    email: "",
    password: "",
  };

  handleSignUp = () => {
    const { email, password } = this.state;
    Firebase.auth()
      .createUserWithEmailAndPassword(email, password)
      .then(() => this.props.navigation.navigate("ProfileScreen"))
      .catch((error) => console.log(error));
  };

  render() {
    return (
      <View style={styles.container}>
        {/* <TextInput
          style={styles.inputBox}
          value={this.state.name}
          placeholder="Full name"
          onChangeText={(name) => this.setState({ name })}
        /> */}
        <TextInput
          style={styles.inputBox}
          value={this.state.email}
          placeholder="Email"
          onChangeText={(email) => this.setState({ email })}
          autoCapitalize="none"
        />
        <TextInput
          style={styles.inputBox}
          value={this.state.password}
          placeholder="Password"
          onChangeText={(password) => this.setState({ password })}
          secureTextEntry={true}
          autoCapitalize="none"
        />
        <TouchableOpacity style={styles.button} onPress={this.handleSignUp}>
          <Text style={styles.buttonText}>Signup</Text>
        </TouchableOpacity>
      </View>
    );
  }
}

export default Signup;

✔ Signup.js

import React from "react";
import { View, Text, StyleSheet } from "react-native";

class Profile extends React.Component {
  render() {
    return (
      <View style={styles.container}>
        <Text>Profile Screen</Text>
      </View>
    );
  }
}

export default Profile;

✔ Profile.js

 

스타일에 관한 부분은 중요하지 않기에 생략했다.

이러한 컴포넌트가 세개가 있을 때 한 컴포넌트에서 다른 컴포넌트로의 이동은 어떻게 하면 좋을까?

 

그러한 정답을 제공해주는 게 react-navigation이다.

이걸 사용하면 다른 컴포넌트의 이동은 물론 props까지 전달할 수 있다.

 

그 방법은 다음과 같다.

우선 세가지 컴포넌트의 상위 컴포넌트가 되는 App 컴포넌트로 간다.

App 컴포넌트에서는 당연히 렌더링할 위의 3가지 컴포넌트들을 import하고 react-navigation도 import한다.

 

import React from "react";
import { StyleSheet, Text, View } from "react-native";
import Login from "./screens/Login";
import Signup from "./screens/Signup";
import Profile from "./screens/Profile";
import { createSwitchNavigator, createAppContainer } from "react-navigation";

const AuthSwitch = createSwitchNavigator(
  {
    LoginScreen: Login,
    SingupScreen: Signup,
    ProfileScreen: Profile,
  },
  { initialRouteName: "SingupScreen" }
);

const AppContainer = createAppContainer(AuthSwitch);

export default AppContainer;

 

보면 순서가 있다.

createSwitchNavigator로 AuthSwitch를 만들어 준후 이 AuthSwitch를 이용하여 createAppContainer로 AppContainer를 생성한다.

  1. AuthSwitch 생성
  2. AppContainer 생성

이런 식이다.

그리고 이 AppContainer를 Routing 해주면 기존 React의 Router 컴포넌트처럼 동작한다.

 

그 중에 "먼저 무슨 컴포넌트를 띄우지?"에 대한 고민을 initialRouteName이 해결해준다.

여기에 제일 먼저 띄우고 싶은 컴포넌트를 설정해주자.

 

그리고 다시 SignupScreen으로 가자!

import React from "react";
import {
  View,
  Text,
  TextInput,
  TouchableOpacity,
  StyleSheet,
} from "react-native";

class Signup extends React.Component {
  state = {
    name: "",
    email: "",
    password: "",
  };

  handleSignUp = () => {
    this.props.navigation.navigate("ProfileScreen");
  };

  render() {
    return (
      <View style={styles.container}>
        {/* <TextInput
          style={styles.inputBox}
          value={this.state.name}
          placeholder="Full name"
          onChangeText={(name) => this.setState({ name })}
        /> */}
        <TextInput
          style={styles.inputBox}
          value={this.state.email}
          placeholder="Email"
          onChangeText={(email) => this.setState({ email })}
          autoCapitalize="none"
        />
        <TextInput
          style={styles.inputBox}
          value={this.state.password}
          placeholder="Password"
          onChangeText={(password) => this.setState({ password })}
          secureTextEntry={true}
          autoCapitalize="none"
        />
        <TouchableOpacity style={styles.button} onPress={this.handleSignUp}>
          <Text style={styles.buttonText}>Signup</Text>
        </TouchableOpacity>
      </View>
    );
  }
}

export default Signup;

TouchableOpacity에 onPress 이벤트리스너를 추가한 걸 보자.

 

🖐🖐 그전에 잠깐!

TouchableOpacity 컴포넌트는 Button 대신에 많이 쓰이는 react-native의 컴포넌트다.

이게 Button 대신에 쓰이는 이유는 Button은 iOS와 안드로이드에서 다르게 보이기 때문에 관리의 어려움이 있기 때문이다.

 

✅그럼 다시 본론으로 돌아와서!

onPress라는 이벤트 리스너는 직감적으로 알 수 있겠지만 터치로 눌렀을 때 함수를 실행한다.

실행되는 함수의 내용은 this.props.navigation.navigate("ProfileScreen")이다.

 

요 3가지 컴포넌트들은 navigation 안에 포함된 녀석들이기 때문에 props안에 navigation이 포함된다.

navigation은 navigate를 통해 원하는 컴포넌트로 전환하는 함수를 가지고 있다.

 

 

이게 전부지만 지금부터는 내가 만난 오류에 대해서 설명하겠다. 🚫🚫

아마 위의 코드를 그대로 실행하면 expo에서 엄청난 오류를 맞이할 것이다.

 

그 이유는 웃기게도 react-navigation을 install 받는 것만으로는 필수 패키지를 충족시키지 못하기 때문이다.

이것 때문에 오류의 늪에 빠져 참 고생을 많이 했는데 해결법은 다음 링크에 포함되어 있다.

 

https://reactnavigation.org/docs/getting-started

 

https://reactnavigation.org/docs/getting-started/

 

reactnavigation.org

 

여기를 보면 react-navigation 외에 어떤 패키지를 install하고 import 해줘야하는지를 설명해주고 있다.

이 과정을 거쳐야 비로소 에러 없이 navigation의 기능을 사용할 수 있다.

 

오늘은 여기까지 하도록 하자. 아르바이트도 있으니까.

내일은 navigation의 기능을 좀 더 파고 auth 서비스를 이용한 회원가입 기능을 전부 구현해볼 것이다.

 

그리고 마지막으로 로그인폼을 작성하면서 새롭게 안 사실에 대해서 추가적으로 기술하자.

모바일에서 텍스트를 입력할 때 알파벳의 경우 첫글자가 자동적으로 대문자로 설정되는 경우가 있다.

이런 경우 때문에 굳이 수고스럽게 shift를 한 번 클릭해주고 입력해야한다.

 

하지만 TextInput에 authcapitalize 속성을 "none"으로 설정하면 첫글자를 자동으로 대문자로 설정하지 않는다.

개꿀!

 

그리고 react-native는 html 태그를 사용하지 않기 때문에 따로 password type의 input이 없다.

그래서 비밀번호를 입력할 때 그 내용이 훤히 다 보인다.

 

이걸 방지하기 위한게 TextInput의 secureTextEntry 속성이다.

이걸 true로 설정하면 입력한 내용이 *로 치환된다.

 

오늘은 여기까지!

그럼 이만~~~

반응형

댓글