В сегодняшнем базовом руководстве по reactnative мы собираемся создать простое приложение, используя reactnative и firebase.

Шаги следующие:

Сначала создайте новый проект React Native:

react-native init ProjectName

Включите параметры разработчика на своем телефоне и включите отладку по USB в параметрах разработчика. В этом руководстве предполагается, что в вашей системе настроен adb.

Выполните следующие команды, чтобы запустить проект на телефоне Android в первый раз:

adb reverse tcp:8081 tcp:8081
cd ProjectName
react-native run-android
react-native start

Когда у вас запущено приложение по умолчанию, включите livereload, встряхнув телефон, чтобы получить параметры разработчика, или выполните следующую команду, чтобы получить его через терминал:

adb shell input keyevent 82

Затем установите модуль firebase npm:

npm install firebase --save

Теперь перейдите в консоль firebase здесь и выберите создать новый проект. Дайте проекту новое имя и выберите свою страну. Это руководство будет охватывать часть Android, поэтому выберите Добавить Firebase в ваше приложение Android и следуйте процедуре. Для имени пакета откройте проект responsenative в студии android и откройте файл манифеста. Имя пакета для проекта response native имеет следующий синтаксис: com.projectname

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.todo"
    android:versionCode="1"
    android:versionName="1.0">

Добавьте какой-нибудь псевдоним проекта и нажмите «Продолжить».

В следующем диалоговом окне загрузите файл googleservices.json и добавьте его в проект студии Android, переключившись на просмотр проекта здесь:

googleservicesjson

Затем установите собственный базовый модуль npm:

npm install --save native-base react-native-vector-icons

Затем выполните следующую команду в зависимости от вашей собственной версии:

  • React Native ‹0,29
    $rnpm link
  • React Native ›= 0,29
    $react-native link react-native-vector-icons

Затем откройте проект responsenative в вашем любимом редакторе и добавьте конфигурацию firebase в index.android.js:

import * as firebase from 'firebase';  // Initialize Firebase
  var fireBaseconfig = {
    apiKey: "Ypur apiKey",
    authDomain: "your auth domain",
    databaseURL: "your db url",
    storageBucket: "your storageBucket",
    messagingSenderId: "your id"
  };
  // firebase.initializeApp(fireBaseconfig);
const firebaseApp = firebase.initializeApp(fireBaseconfig);

Чтобы получить firebaseconfig, перейдите в консоль firebase. Нажмите на значок шестеренки в левом меню рядом с названием проекта. Нажмите на настройки проекта. На вкладке «Общие» перейдите в раздел «Ваши приложения» и нажмите кнопку ДОБАВИТЬ ПРИЛОЖЕНИЕ. Нажмите «Добавить firebase». в ваше веб-приложение. В открывшемся диалоговом окне скопируйте только содержимое config json и вставьте его в fireBaseconfig json в свое приложение.

создайте новую папку с именем src со страницами и папкой стилей, например:

тодофилет

Папка src содержит три компонента, а именно страницу входа, страницу регистрации и главную страницу, на которые нужно перейти после успешного входа в систему.

Страница стилей содержит общие стили для всех страниц:

'use strict';
import React, {
  StyleSheet
} from 'react-native';
module.exports = StyleSheet.create({
  container: {
    alignItems: 'stretch',
    flex: 1
  },
  body: {
    flex: 9,
    flexDirection:'row',
    alignItems:'center',
    justifyContent:'center',
    backgroundColor: '#F5FCFF',
  },
  primaryButton: {
    margin: 10,
    padding: 15,
    alignSelf:'center',
    backgroundColor:"blue",
    width:150
  },
});

Страница входа создается следующим образом:

'use strict';
import {
  AppRegistry,
  AsyncStorage,
  View,
  ToolbarAndroid,
  ActivityIndicator
} from 'react-native';
import { Header,Container,Title, Content, List, ListItem, InputGroup, Input, Icon, Text, Picker, Button } from 'native-base';
import React, {Component} from 'react';
 import Signup from './Signup';
import Account from './Main'
import styles from '../styles/mainstyle.js';
export default class Login extends Component {
  constructor(props){
    super(props);
    // We have the same props as in our signup.js file and they serve the same purposes.
    this.state = {
      loading: false,
      email: '',
      password: ''
    }
  }
  render() {
    // The content of the screen should be inputs for a username, password and submit button.
    // If we are loading then we display an ActivityIndicator.
    const content = this.state.loading ?
    <View style={styles.body}>
    <ActivityIndicator size="large"/>
    </View> :
    <Content>
                   <List>
                     <ListItem>
                         <InputGroup>
                         <Icon name="ios-person" style={{ color: '#0A69FE' }} />
                         <Input
                          onChangeText={(text) => this.setState({email: text})}
                          value={this.state.email}
                          placeholder={"Email Address"} />
                          </InputGroup>
                    </ListItem>
                    <ListItem>
                        <InputGroup>
                          <Icon name="ios-unlock" style={{ color: '#0A69FE' }} />
                        <Input
                          onChangeText={(text) => this.setState({password: text})}
                          value={this.state.password}
                          secureTextEntry={true}
                          placeholder={"Password"} />
                        </InputGroup>
                   </ListItem>
                  </List>
                  <Button style={styles.primaryButton} onPress={this.login.bind(this)}>
                    Login
                  </Button>
                  <Button onPress={this.goToSignup.bind(this)} style={styles.primaryButton}>
                    New Here?
                  </Button>
          </Content>
        ;
    // A simple UI with a toolbar, and content below it.
        return (
                  <Container>
                            <Header>
                              <Title>Login</Title>
                           </Header>
                  {content}
                </Container>
                );
  }
  login(){
    this.setState({
      loading: true
    });
    // Log in and display an alert to tell the user what happened.
    this.props.firebaseApp.auth().signInWithEmailAndPassword(this.state.email, this.state.password
    ).then((userData) =>
      {
        this.setState({
                loading: false
              });
              AsyncStorage.setItem('userData', JSON.stringify(userData));
              this.props.navigator.push({
                component: Account
              });
      }
    ).catch((error) =>
        {
              this.setState({
                loading: false
              });
        alert('Login Failed. Please try again'+error);
    });
  }
  // Go to the signup page
  goToSignup(){
    this.props.navigator.push({
      component: Signup
    });
  }
}
AppRegistry.registerComponent('Login', () => Login);

Здесь мы используем компоненты Nativebase для разработки нашего пользовательского интерфейса. Перейдите в docs по nativebase для получения дополнительных сведений.

Позже мы передадим навигатор и firebaseapp как свойства из index.android.js. Для простоты предположим, что компоненты получили их как свойства.

Функция обработчика входа в систему сначала использует метод аутентификации firebase для входа пользователя при получении действительных учетных данных, в противном случае отображается предупреждение об ошибке. Затем он сохраняет пользовательские данные в хранилище локального устройства с помощью модуля Asyncstorage, что позволяет нам сохранить вход пользователя в систему, даже когда приложение убито, аналогично общим настройкам в родном Android. Компонент Gotosignup направляет пользователя на регистрацию, если учетная запись пользователя еще не создана.

Страница регистрации имеет аналогичную структуру:

'use strict';
import {
  AppRegistry,
  View,
  ToolbarAndroid,
  ActivityIndicator
} from 'react-native';
import { Header,Title,Container, Content, List, ListItem, InputGroup, Input, Icon, Text, Picker, Button } from 'native-base';
import styles from '../styles/mainstyle.js';
import React, {Component} from 'react';
import Login from './Login';
export default class Signup extends Component {
  constructor(props) {
    super(props);
    this.state = {
      // used to display a progress indicator if waiting for a network response.
      loading: false,
      // entered credentials
      email: '',
      password: ''
    }
  }
  // A method to passs the username and password to firebase and make a new user account
  signup() {
    this.setState({
      // When waiting for the firebase server show the loading indicator.
      loading: true
    });
    // Make a call to firebase to create a new user.
    this.props.firebaseApp.auth().createUserWithEmailAndPassword(
      this.state.email,
      this.state.password).then(() => {
        // then and catch are methods that we call on the Promise returned from
        // createUserWithEmailAndPassword
        alert('Your account was created!');
        this.setState({
          // Clear out the fields when the user logs in and hide the progress indicator.
          email: '',
          password: '',
          loading: false
        });
        this.props.navigator.push({
          component: Login
        });
    }).catch((error) => {
      // Leave the fields filled when an error occurs and hide the progress indicator.
      this.setState({
        loading: false
      });
      alert("Account creation failed: " + error.message );
    });
  }
  render() {
    // The content of the screen should be inputs for a username, password and submit button.
    // If we are loading then we display an ActivityIndicator.
    const content = this.state.loading ? <ActivityIndicator size="large"/> :
           <Content>
                <List>
                 <ListItem>
                     <InputGroup>
                     <Icon name="ios-person" style={{ color: '#0A69FE' }} />
                     <Input
                      onChangeText={(text) => this.setState({email: text})}
                      value={this.state.email}
                      placeholder={"Email Address"} />
                      </InputGroup>
                </ListItem>
                <ListItem>
                    <InputGroup>
                      <Icon name="ios-unlock" style={{ color: '#0A69FE' }} />
                    <Input
                      onChangeText={(text) => this.setState({password: text})}
                      value={this.state.password}
                      secureTextEntry={true}
                      placeholder={"Password"} />
                    </InputGroup>
               </ListItem>
              </List>
              <Button style={styles.primaryButton} onPress={this.signup.bind(this)}>
                Signup
              </Button>
              <Button onPress={this.goToLogin.bind(this)} style={styles.primaryButton}>
                Go to Login
              </Button>
      </Content>
    ;
    // A simple UI with a toolbar, and content below it.
        return (
                  <Container>
                  <Header>
                     <Title>Sign Up</Title>
                  </Header>
                  {content}
                  </Container>
                )
  }
  goToLogin(){
    this.props.navigator.push({
      component: Login
    });
  }
}
AppRegistry.registerComponent('Signup', () => Signup);

Обработчик регистрации создает нового пользователя, используя createUserWithEmailAndPassword метода аутентификации firebase, а затем перенаправляет пользователя на страницу входа.

Главная страница структурирована следующим образом:

'use strict';
import {
  AppRegistry,
  ActivityIndicator,
  AsyncStorage,
  StyleSheet,
  Text,
  View,
  Image,
  TouchableHighlight,
  ToolbarAndroid
} from 'react-native';
import React, {Component} from 'react';
import { Header,Container,Title, Content, List, ListItem, InputGroup, Input, Icon, Picker, Button } from 'native-base';
import Login from './Login';
import styles from '../styles/mainstyle.js';
// Styles specific to the account page
const accountStyles = StyleSheet.create({
  email_container: {
    padding: 20
  },
  email_text: {
    fontSize: 18
  }
});
export default class Account extends Component {
  constructor(props) {
    super(props);
    this.state = {
      user:null,
      loading: true,
    }
  }
  componentWillMount() {
    // get the current user from firebase
    // const userData = this.props.firebaseApp.auth().currentUser;
    AsyncStorage.getItem('userData').then((user_data_json) => {
      let userData = JSON.parse(user_data_json);
      this.setState({
        user: userData,
        loading: false
      });
    });
  }
  render() {
    // If we are loading then we display the indicator, if the account is null and we are not loading
    // Then we display nothing. If the account is not null then we display the account info.
    const content = this.state.loading ?
    <ActivityIndicator size="large"/> :
       this.state.user &&
                 <Content>
                    <View style={accountStyles.email_container}>
                      <Text style={accountStyles.email_text}>{this.state.user.email}</Text>
                    </View>
                    <Image
                      style={styles.image}
                      source={{uri: this.state.user.photoURL}} />
                    <Button onPress={this.logout.bind(this)} style={styles.primaryButton}>
                      Logout
                    </Button>
                </Content>
      ;
      // console.log("loading user",this.state.user,this.state.loading);
    return (
        <Container>
        <Header>
            <Title>Header</Title>
        </Header>
          {content}
      </Container>
    );
  }
  logout() {
    // logout, once that is complete, return the user to the login screen.
    AsyncStorage.removeItem('userData').then(() => {
      this.props.firebaseApp.auth().signOut().then(() => {
        this.props.navigator.push({
          component: Login
        });
      });  
    });
  }
}
AppRegistry.registerComponent('Account', () => Account);

Здесь мы пытаемся получить userData во время первоначального рендеринга в методе componentWillMount из Asyncstorage. Onlogouthandler удаляет данные из asyncstorage, а затем уничтожает сеанс из firebase.

Теперь перейдите в index.android.js и внесите следующие изменения:

import React, { Component } from 'react';
import {
  AppRegistry,
  ActivityIndicator,
  AsyncStorage,
  StyleSheet,
  Navigator,
  Text,
  View,
  ToolbarAndroid
} from 'react-native';
//Pages
import Signup from './src/pages/Signup';
import Login from './src/pages/Login';
import Account from './src/pages/Main';
import styles from './src/styles/mainstyle.js'
import * as firebase from 'firebase';  // Initialize Firebase
  var fireBaseconfig = {
    apiKey: "Ypur apiKey",
    authDomain: "your auth domain",
    databaseURL: "your db url",
    storageBucket: "your storageBucket",
    messagingSenderId: "your id"
  };
  // firebase.initializeApp(fireBaseconfig);
const firebaseApp = firebase.initializeApp(fireBaseconfig);
export class todo extends Component {
  constructor(props){
    super(props);
    this.state={
      openingPage: null
    }
  }
  componentWillMount(){
    //Check if userData is stored on device else open Login
    AsyncStorage.getItem('userData').then((user_data_json) => {
      let user_data = JSON.parse(user_data_json);
      let openingPage = {openingPage: Login};
      if(user_data != null){
        this.setState({openingPage:Account});
      }else{
        this.setState(openingPage);
      }
    });
  }
  render() {
    if (this.state.openingPage) {
      return (
        // Take the user to whatever page we set the state to.
        // We will use a transition where the new page will slide in from the Left.
        <Navigator
          initialRoute={{component: this.state.openingPage}}
          configureScene={() => {
            return Navigator.SceneConfigs.HorizontalSwipeJumpFromLeft;
          }}
          renderScene={(route, navigator) => {
            if(route.component){
              // Pass the navigator the the page so it can navigate as well.
              // Pass firebaseApp so it can make calls to firebase.
              return React.createElement(route.component, { navigator, firebaseApp});
            }
        }} />
      );
    } else {
      return (
        // Our default loading view while waiting to hear back from firebase
        <View style={styles.container}>
          <ToolbarAndroid title="Login" />
          <View style={styles.body}>
            <ActivityIndicator size="large" />
          </View>
        </View>
      );
}
  }
}

AppRegistry.registerComponent('todo', () => todo);

В методе componentWillMount мы проверяем, хранятся ли данные пользователя локально, и перенаправляем пользователя на логин или на главную страницу. Метод рендеринга содержит простой навигатор, который передает навигатор и firebaseapp в качестве свойств другим компонентам.

Страницы приложений выглядят следующим образом:

страница авторизации

Главная страница

Хранение пользовательских данных напрямую с использованием хранилища Async может быть не очень хорошей практикой, и пользовательские данные могут передаваться в качестве реквизита другим компонентам вместо того, чтобы каждый раз вызывать методы asyncstorage, но основная цель этой статьи заключалась в том, чтобы просто охватить основы reactnative, firebase и nativestack.

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

Пожалуйста, отметьте свои сомнения, рекомендации и предложения в разделе комментариев и нажмите ♥, если хотите порекомендовать это другим.

Ознакомьтесь с моими другими уроками по адресу: