React-Native и Firebase - Часть первая Простая аутентификация

Итак, я медленно продвигался в своем пивном приложении и недавно завершил аутентификацию, поэтому решил, что пришло время для другого поста. Я выбрал Firebase, так как раньше возился с ним, и помню, что он довольно хорошо подходит для мобильных приложений, к тому же интерфейс довольно приятный.

Я предполагаю, что у всех вас есть настройка скелета приложения с использованием либо response-native init, либо create-react-native-app.

Настройка проекта React-Native

Поскольку я использовал init-native init, первое, что я делаю, это создаю файл App.js в корне, копирую и вставляю код из index.ios.js или index.android.js и вставьте его в App.js, чтобы он выглядел примерно так.

import React, { Component } from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  View
} from 'react-native';
export default class myapp extends Component {
  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.welcome}>
          Welcome to React Native!
        </Text>
        <Text style={styles.instructions}>
          To get started, edit index.ios.js
        </Text>
        <Text style={styles.instructions}>
          Press Cmd+R to reload,{'\n'}
          Cmd+D or shake for dev menu
        </Text>
      </View>
    );
  }
}
const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
  instructions: {
    textAlign: 'center',
    color: '#333333',
    marginBottom: 5,
  },
});
AppRegistry.registerComponent('myapp', () => myapp);

Затем в каждый из index.android.js и index.ios.js добавьте следующую строку:

import "./App";

Это немного упрощает работу, поскольку вам нужно беспокоиться только о редактировании одного файла, и изменения будут отражены как в версиях приложения для iOS, так и в Android. Очевидно, что в зависимости от того, что вы делаете, некоторые функции могут быть доступны только на определенных платформах / выглядеть по-разному на каждой платформе, поэтому по мере роста сложности вашего приложения вы можете редактировать каждый соответствующий файл отдельно, но для с этой целью он отлично работает.

Я знаю, что есть несколько разных способов настроить вашу файловую структуру с помощью React Project, это способ, который я читал / принимал на данный момент, если вы думаете, что это можно было бы сделать лучше, пожалуйста, оставьте комментарий ниже!

Удалите все стили из файла App.js, мы создадим отдельную таблицу стилей для каждой страницы, поскольку некоторые стили будут специфичными для каждой страницы в приложении. Затем создайте папку «app» в корне проекта и внутри нее создайте папку «component», в которой будут размещаться все наши страницы приложений, а также любые компоненты, которые мы создаем. Каталог вашего проекта, если вы используете init-native init, будет выглядеть примерно так, как показано ниже.

Настройка Firebase

Перейдите на firebase и войдите в систему (зарегистрируйтесь, если вы еще этого не сделали, с помощью своей учетной записи Gmail). Затем вы можете Добавить проект и ввести название своего приложения, а также выбрать страну / регион, в котором вы находитесь. Как только это будет сделано, вы попадете на экран панели управления вашего приложения, который выглядит примерно так.

Вам нужно будет нажать «Добавить Firebase в свое веб-приложение», после чего появится всплывающее окно с деталями конфигурации.

Очевидно, он создан для веб-приложения, поэтому нам нужно будет преобразовать его в чистый JS для работы с React-Native. Затем мы инициализируем приложение Firebase в методе componentWillMount (), это обеспечит его вызов перед первоначальной отрисовкой компонента.

Было бы неплохо использовать react-native-dotenv, чтобы не показывать миру свои живые ключи api. Его очень легко настроить: просто создайте файл .env, добавьте его в свой файл .gitignore, вставьте туда все свои переменные env и импортируйте их туда, где вам нужно. их.

import {
   FIREBASE_API_KEY,
   AUTH_DOMAIN,
   DATABASE_URL,
   FIREBASE_PROJECT_ID,
   FIREBASE_STORAGE_BUCKET,
   MESSAGE_ID
} from 'react-native-dotenv';
componentWillMount() {
        firebase.initializeApp({
            apiKey: FIREBASE_API_KEY,
            authDomain: AUTH_DOMAIN,
            databaseURL: DATABASE_URL,
            projectId: FIREBASE_PROJECT_ID,
            storageBucket: FIREBASE_STORAGE_BUCKET,
            messagingSenderId: MESSAGE_ID
        });
    }

Создание формы регистрации / входа

Мы извлечем нашу форму ввода текста в отдельный компонент, так как мы будем повторно использовать ее для ввода адреса электронной почты, пароля, имени или любых других данных, которые мы хотим сохранить. В папке «component» создайте новый файл TextInputField.js и введите приведенный ниже код.

import React, { Component } from 'react';
import { View, Text, TextInput } from 'react-native';
import styles from './styles.js';
const TextFieldInput = ({ label, value, onChangeText, placeholder, secureTextEntry }) => {
const { inputStyle, labelStyle, containerStyle } = styles;
return (
        <View style={containerStyle}>
            <Text>{label}</Text>
            <TextInput
                autoCorrect={false}
                placeholder={placeholder}
                secureTextEntry={secureTextEntry}
                value={value}
                onChangeText={onChangeText}
                style={inputStyle}
                underlineColorAndroid={'transparent'}
                autoCorrect={false}
            />
        </View>
    );
};
export default TextFieldInput;

Причина, по которой я выделил ввод, заключалась в том, что вам действительно нужно вводить эти данные построчно, это поможет вам понять, что вы на самом деле делаете. Это довольно просто, но давайте разберемся, чтобы увидеть, что мы здесь делаем.

Мы импортируем все, что нам нужно, вы заметите, что я уже настроил некоторые стили в отдельном файле, который мы рассмотрим через секунду. Начнем с создания константы TextFieldInput, которая будет принимать аргументы метка, значение, onChangeText, заполнитель и secureTextEntry. Затем в нашей функции мы определяем нашу константу стили, которая позволяет нам определять, какие стили использовать и откуда их брать. Затем мы настраиваем View, используя наш containerStyle и TextInput,, который будет иметь значение текстового заголовка любого label установлен на. Затем мы определяем каждый из параметров TextInput на основе аргументов, которые мы определили ранее. Вы заметите, что я также добавил «underlineColorAndroid = {‘ transparent ’}”. На Android вы получаете это странное подчеркивание, которое выглядит довольно беспорядочно, эта строка в основном избавляется от него. Наконец, мы экспортируем наш новый компонент, готовый к импорту, где бы мы его ни использовали.

Теперь мы готовы создать нашу форму входа / регистрации, а затем создать папку SignInForm в нашей папке «app». Затем создайте index.js и styles.js. Ниже представлен завершенный фрагмент для нашей страницы SignInForm. Давайте разберем его и посмотрим, что представляет собой каждый раздел. на самом деле делаю.

import React, { Component } from 'react’;
import { View, Text, Button } from 'react-native’;
import firebase from 'firebase’;
import TextInputField from '../component’;
import styles from './styles.js’;
class SignInForm extends Component {
    state = { email: '', password: '', error: '', loading: false };
    onSignInPress() {
        this.setState({ error: '', loading: true });
const { email, password } = this.state;
        firebase.auth().signInWithEmailAndPassword(email, password)
            .then(() => { this.setState({ error: '', loading: false }); })
            .catch(() => {
                firebase.auth().createUserWithEmailAndPassword(email, password)
                    .then(() => { this.setState({ error: '', loading: false }); })
                    .catch(() => {
                        this.setState({ error: 'Authentication failed.', loading: false });
                    });
            });
    }
    renderButtonOrLoading() {
        if (this.state.loading) {
            return <View><ActivityIndicator /></View>
        }
        return <Button onPress={this.onSignInPress.bind(this)} title="Log in" />;
    }
    render() {
        return (
            <View>
                    <TextFieldInput
                        label='Email Address'
                        placeholder='[email protected]'
                        value={this.state.email}
                        onChangeText={email => this.setState({ email })}
                        autoCorrect={false}
                    />
                    <TextFieldInput
                        label='Password'
                        autoCorrect={false}
                        placeholder='Your Password'
                        secureTextEntry
                        value={this.state.password}
                        onChangeText={password => this.setState({ password })}
                    />
                    <Text style={styles.errorTextStyle}>{this.state.error}</Text>
                    {this.renderButtonOrLoading()}
            </View>
        );
    }
}
export default SignInForm;

Здесь мы, очевидно, просто импортируем все, что нам нужно, обратите внимание, что мы вводим наш TextFieldInput, который мы создали ранее, а также наши стили, которые мы извлекаем в отдельный файл для более чистый код.

import React, { Component } from 'react’;
import { View, Text, Button } from 'react-native’;
import firebase from 'firebase’;
import TextFieldInputField from '../component’;
import styles from './styles.js’;

Теперь мы создаем нашу SignInForm. Начнем с установки состояния четырех переменных: электронная почта, пароль, ошибка и загрузка.

class SignInForm extends Component {
    state = { email: '', password: '', error: '', loading: false };
    onSignInPress() {
        this.setState({ error: '', loading: true });
const { email, password } = this.state;
        firebase.auth().signInWithEmailAndPassword(email, password)
            .then(() => { this.setState({ error: '', loading: false }); })
            .catch(() => {
                
                firebase.auth().createUserWithEmailAndPassword(email, password)
                    .then(() => { this.setState({ error: '', loading: false }); })
                    .catch(() => {
                        this.setState({ error: 'Authentication failed.', loading: false });
                    });
            });
    }

Затем мы создаем функцию OnSignInPress, устанавливаем состояние ошибки на пустую строку, а для загрузки - значение true. Затем мы устанавливаем константу, содержащую адрес электронной почты и пароль, и устанавливаем их равными this.state. При этом будут сохранены значения адреса электронной почты и пароля, введенные в форму. Затем мы вызываем метод signInWithEmailAndPassword firebase и передаем ему аргументы электронной почты и пароля. Затем мы вызываем средство обнаружения ошибок, которое, если вход в систему был неудачным, т. Е. Пользователь не существует, вызывается метод firebase createUserWithEmailAndPassword, который передается с адресом электронной почты и пароль аргументы. Это создаст нового пользователя, который практически мгновенно появится в вашей консоли firebase. Наконец, если что-то не удается, например, вы вводите адрес электронной почты без пароля, для ошибки устанавливается значение Ошибка аутентификации, которая затем отображается для пользователя. Это в значительной степени основа аутентификации. Если вам интересно, зайдите в документацию, есть множество других способов аутентификации, включая номер телефона, в следующий раз я пройду через социальные сети и все такое прочее.

Следующая функция renderButtonOrLoading (), как следует из названия, отображает кнопку или сообщение Загрузка. По сути, мы визуализируем нашу переменную loading из ранее, и если это правда, она будет отображать текст Загрузка…, мы, очевидно, можем добавить сюда причудливую анимацию, но я оставлю это вам. Затем мы визуализируем нашу кнопку входа в систему, которая привязана к нашей функции onSignInPress, поэтому при каждом нажатии кнопки функция запускается.

renderButtonOrLoading() {
        if (this.state.loading) {
            return <Text>Loading...</Text>
        }
        return <Button onPress={this.onSignInPress.bind(this)} title="Sign in" />;
    }

Наконец, мы визуализируем представление. Здесь мы добавляем наш компонент TextInputField, который мы создали ранее. Мы вводим значение метки, текст заполнителя и устанавливаем переменную состояния адрес электронной почты, равную тому, что введено в текстовое поле. Практически то же самое касается поля «Пароль», за исключением дополнительных параметров автозамена и SecureTextEntry, которые, как следует из названия, обеспечивают скрытие пароля от просмотра с помощью •• •••• или ****** символы. Последнее, что мы делаем, это экспортируем все это целиком, чтобы мы могли вызвать его в нашем файле App.js.

render() {
        return (
            <View>
                    <TextInputField
                        label=’Email Address'
                        placeholder=’[email protected]'
                        value={this.state.email}
                        onChangeText={email => this.setState({ email })}
                        autoCorrect={false}
                    />
                    <TextInputField
                        label=’Password'
                        autoCorrect={false}
                        placeholder=’Your Password'
                        secureTextEntry
                        value={this.state.password}
                        onChangeText={password => this.setState({ password })}
                    />
                    <Text style={styles.errorTextStyle}>{this.state.error}</Text>
                    {this.renderButtonOrLoading()}
            </View>
        );
    }
}
export default SignInForm;

Это простое содержимое нашего файла style.js в нашей папке SignInForm. Это довольно понятно.

'use strict';
import React, {
  StyleSheet
} from 'react-native';
const styles = StyleSheet.create({
errorTextStyle: {
        color: '#E64A19',
        alignSelf: 'center',
        paddingTop: 10,
        paddingBottom: 10
    }
});
export default styles;

Пока мы делаем таблицы стилей, вот та, которая находится в нашей папке component. Опять же, нет смысла обсуждать это, поскольку это довольно просто. Не стесняйтесь поиграть с ним, сделайте его своим.

'use strict';
import React, {
  StyleSheet
} from 'react-native';
const styles = StyleSheet.create({
inputStyle: {
       paddingRight: 5,
       paddingLeft: 5,
       paddingBottom: 2,
       color: 'black',
       fontSize: 18,
       fontWeight: '200',
       flex: 1,
       height: 100,
       width: 300,
       borderColor: 'gray',
       borderWidth: 1,
},
   containerStyle: {
       height: 45,
       flexDirection: 'column',
        alignItems: 'flex-start',
        width: '100%',
        borderColor: 'gray',
       borderBottomWidth: 1,
   }
});
export default styles;

Последняя часть головоломки - собрать все это воедино в нашем файле App.js. Вот на что должен напоминать конечный результат.

import React, { Component } from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  View
} from 'react-native';
import Config from 'react-native-config';
import {
   FIREBASE_API_KEY,
   AUTH_DOMAIN,
   DATABASE_URL,
   FIREBASE_PROJECT_ID,
   FIREBASE_STORAGE_BUCKET,
   MESSAGE_ID
} from 'react-native-dotenv';
import * as firebase from 'firebase';
import SignInForm from './app/SignInForm';
export default class myapp extends Component {
componentWillMount() {
        firebase.initializeApp({
            apiKey: FIREBASE_API_KEY,
            authDomain: AUTH_DOMAIN,
            databaseURL: DATABASE_URL,
            projectId: FIREBASE_PROJECT_ID,
            storageBucket: FIREBASE_STORAGE_BUCKET,
            messagingSenderId: MESSAGE_ID
        });
    }
  render() {
    return (
      <View>
       <SignInForm />
      </View>
    );
  }
}
AppRegistry.registerComponent('myapp', () => myapp);

Теперь, не допуская сбоев, запустите react-native run-ios или react-native run-android. Я предполагаю, что вы либо подключили свой телефон к ноутбуку и включили отладку, либо настроили симулятор и готовы к работе (это применимо только для Android, iOS должна просто загружать его, когда вы вызываете команду) .

Теперь откройте консоль Firebase и перейдите на вкладку Аутентификация справа. При входе в приложение и нажатии кнопки «Войти» ваш пользователь должен появиться в консоли, как по волшебству!

Бум! Готово. Теперь, очевидно, есть еще много дел, но вы уже реализовали основы. В следующий раз мы рассмотрим интеграцию учетных записей социальных сетей через Facebook / Google / Twitter и способы управления навигацией после завершения входа в систему / регистрации.

Спасибо за чтение, нажмите 💚, если вам нравится то, что вы читаете, и обязательно подпишитесь, чтобы быть в курсе будущих публикаций.