How to make group chat in React-Native using firebase (Realtime database).



I was sceptical about Firebase with react-native. But after using Firebase with react-native, realised me that it’s awesome. Using Firebase is able to speed up mobile app and web app developmentā€Š. Here i am going to create a cool app A group chat using firebase real time database with react-native. 

            


Firebase Setup

Step 1:– Go to Firebase Setup . Login if you are not. or  Go to https://firebase.google.com and click on Go to Console on the top right of the Screen. You need to make sure you are using latest version of firebase.

Step 2:-  Create new project. Fill up your project name and region name.

      

Step 3:-  Click on Add Firebase to your web app.

      .

Step 4:-   After clicking Add Firebase to your web app,  a dialog box will be open. There is all credential like apiKey, authDomain, databaseURL, ProjectId, storageBucket  just copy that it will used in react-native project.

      

Step 5:-  Close the dialog box. and Click on Database on left side list and click on Get Started in Realtime Database. There is four tabs.  In data, all the data stored.  before we using database, change the rules. Click on Rules tab and replace code from following code.

{
“rules”: {
“.read”: true,
“.write”: true
}
}

     

Now we have successfully setup Firebase for react-native database.

Create a React-Native project.

Step 1:- Create a new React-Native Project.

 react-native init  ReactNativeFirebase

Step 2:- Install npm firebase.

npm install –save firebase

Step 3:-  Install npm react-navigation

npm install –save react-navigation

Step 4:- Create folder app inside the project. Inside the app folder create two folder.

  • app/components
  • app/pages

Step 5:- Create the following files.

  • app/index.js
  • app/pages/firebaseFile.js
  • app/pages/home.js
  • app/pages/style.js
  • app/components/ActionButton.js
  • app/components/ListItem.js
  • app/components/StatusBar.js
  • app/components/messageInput.js

Step 6:- Replace the index.android.js and index.ios.js with following code.

import ‘./app/index’

Step 7:- app/index.js

import React, { Component } from 'react';
import {  AppRegistry} from 'react-native';
import { StackNavigator } from 'react-navigation';
import FirebasePage from './pages/firebaseFile';
import Home from './pages/home';

const App = StackNavigator({
 home: {screen: Home},
 firebasePage: {screen: FirebasePage},
});

AppRegistry.registerComponent('PushNotifiction', () => App);

Step 8:- app/pages/firebaseFile.js

'use strict';

import React, {Component} from 'react';
import ReactNative from 'react-native';
const firebase = require('firebase');
const StatusBar = require('../components/StatusBar');
const MessageInput = require('../components/messageInput');
const ListItem = require('../components/ListItem');
const styles = require('./styles.js')

import {
  AppRegistry,
  ListView,
  StyleSheet,
  Text,
  View,
  AsyncStorage,
  TouchableHighlight,
  AlertIOS,
} from 'react-native';

// Initialize Firebase
const firebaseConfig = {
  apiKey: "AIzaSyBkP3ovBefuls9MTZ9X176MqORlVqAlpck",
  authDomain: "reactfirebase-e69e0.firebaseapp.com",
  databaseURL: "https://reactfirebase-e69e0.firebaseio.com",
  storageBucket: "reactfirebase-e69e0.appspot.com",
};
const firebaseApp = firebase.initializeApp(firebaseConfig);

export default class FirebaseReactNativeSample extends Component {
static navigationOptions = {
    headerMode: 'none',
    header: null,
    gesturesEnabled: false
  }
  constructor(props) {
    super(props);
    this.state = {
      text: '',
      user: '',
      navigate: this.props.navigation.navigate,
      dataSource: new ListView.DataSource({
        rowHasChanged: (row1, row2) => row1 !== row2,
      })
    };
    this.itemsRef = this.getRef().child('items');
    this.itemsReference = this.getRef().child('name');
  }

  getRef() {
    return firebaseApp.database().ref();
  }

  listenForItems(itemsRef) {
    itemsRef.on('value', (snap) => {

      // get children as an array
      console.log(snap)
      var itemsListView = [];
      snap.forEach((child) => {
        itemsListView.push({
          title: child.val().title,
          _key: child.key,
          name: child.val().name,
        });
      });
      console.log(itemsListView)
      this.setState({
        dataSource: this.state.dataSource.cloneWithRows(itemsListView)
      });
    });
  }

  componentDidMount() {
    this.listenForItems(this.itemsRef);
  }

  render() {
    return (
       <View style={styles.container}>
        <StatusBar title="React Native Group Chat" />
        <ListView
           dataSource={this.state.dataSource}
           renderRow={this._renderItem.bind(this)}
           enableEmptySections={true}
           style={styles.listview}/>
         <MessageInput onPress={this._addItem.bind(this)} title="Send" onChangeText={(text) => this.setState({text})} value={this.state.text}/>
         </View>
    )
  }

  _addItem() {
    this.itemsRef.push({ title: this.state.text, name: this.state.user})
    this.setState({text: ''})
  }
  _renderItem(item) {
    const onPress = () => {
      AlertIOS.alert(
        'Complete',
        null,
        [
          {text: 'Complete', onPress: (text) => this.itemsRef.child(item._key).remove()},
          {text: 'Cancel', onPress: (text) => console.log('Cancelled')}
        ]
      );
    };

    return (
       <ListItem item={item} onPress={onPress} />
    );
  }

}


Step 9:-  app/pages/home.js

import React, {Component} from 'react';
import ReactNative from 'react-native';
import {
  View, 
  Text,
  TouchableOpacity,
  TextInput,
  AsyncStorage,
} from 'react-native';
import ActionButton from '../components/ActionButton';
import styles from './styles'

export default class Home extends Component {
  static navigationOptions = {
    headerMode: 'none',
    header: null,
    gesturesEnabled: false
  }
  constructor(props) {
    super(props);
    this.state = {
      text: '',
      navigate: this.props.navigation.navigate,
    };
    this.onSubmit=this.onSubmit.bind(this)
  }

 componentWillMount(){
    AsyncStorage.getItem('userName').then((value) => {
      this.setState({user: value})
    }).done();
  }

  onSubmit(){
    if(this.state.text !='') {
      AsyncStorage.setItem('userName', this.state.text);
      this.state.navigate('firebasePage');
    }
  }
  render() {
    return (
      <View style={styles.homeContainer}>
        <Text style={styles.titleText}>Welcome React Native Team</Text>
        <TextInput
          style={styles.inputField}
          onChangeText={(text) => this.setState({text})}
          value={this.state.text}
          placeholder={"Enter your name"}
        />
        <ActionButton onPress={this.onSubmit} title="SUBMIT" />
      </View>
    )
  }
}

Step 10:- app/pages/style.js

const React = require('react-native')
const {StyleSheet, Dimensions} = React
const constants = {
  actionColor: '#24CE84'
};
const {height, width}= Dimensions.get('window')
var styles = StyleSheet.create({
  container: {
    backgroundColor: '#f2f2f2',
    flex: 1,
  },
  listview: {
    flex: 1,
  },
  li: {
    backgroundColor: '#fff',
    borderBottomColor: '#eee',
    borderColor: 'transparent',
    borderWidth: 1,
    paddingLeft: 16,
    paddingTop: 14,
    paddingBottom: 16,
  },
  liContainer: {
    flex: 2,
  },
  liText: {
    color: '#333',
    fontSize: 16,
  },
  liTextName: {
    color: '#24CE84',
    fontSize: 16,
  },
  navbar: {
    alignItems: 'center',
    backgroundColor: '#fff',
    borderBottomColor: '#eee',
    borderColor: 'transparent',
    borderWidth: 1,
    justifyContent: 'center',
    height: 44,
    flexDirection: 'row'
  },
  navbarTitle: {
    color: '#444',
    fontSize: 16,
    fontWeight: "500"
  },
  statusbar: {
    backgroundColor: '#fff',
    height: 22,
  },
  center: {
    textAlign: 'center',
  },
  actionText: {
    color: '#fff',
    fontSize: 16,
    textAlign: 'center',
    alignSelf: 'center'
  },
  action: {
    backgroundColor: constants.actionColor,
    borderColor: 'transparent',
    borderWidth: 1,
    paddingLeft: 16,
    paddingTop: 14,
    paddingBottom: 16,
  },
  ActionButton: {
    backgroundColor: constants.actionColor,
    borderColor: 'transparent',
    borderWidth: 1,
    paddingLeft: 16,
    paddingTop: 14,
    paddingBottom: 16,
    width: width / 4,
    alignItems: 'center',
    justifyContent: 'center',
  },
  homeContainer: {
    backgroundColor: '#f2f2f2',
    flex: 1,
    justifyContent: 'center',
  },
  titleText: {
    fontSize: 20,
    alignSelf: 'center',
  },
  inputField: {
    marginTop: 40,
    marginBottom: 40,
    width: width,
    height: 40,
    borderBottomColor: 'gray',
    borderBottomWidth: 1,
    alignSelf: 'center',
  },
  buttonView: {
    backgroundColor: 'red',
  },
  msgContainer: {
    flexDirection: 'row',
  },
  msgInputField: {
    width: width/ 1.3,
    height: 40,
    borderBottomColor: 'gray',
    borderBottomWidth: 1,
    alignSelf: 'center',
  }
})

module.exports = styles
module.exports.constants = constants;

Step 11:- app/components/ActionButton.js

'use strict';

import React, {Component} from 'react';
import ReactNative from 'react-native';
const styles = require('../pages/styles.js')
const constants = styles.constants;
const { StyleSheet, Text, View, TouchableHighlight} = ReactNative;

class ActionButton extends Component {
  render() {
    return (
     <View style={styles.action}>
       <TouchableHighlight
         underlayColor={constants.actionColor}
         onPress={this.props.onPress}>
       <Text style={styles.actionText}>{this.props.title}</Text>
       </TouchableHighlight>
    </View> 
    );
  }
}

module.exports = ActionButton;





Step 12:- app/components/ListItem.js

import React, {Component} from 'react';
import ReactNative from 'react-native';
const styles = require('../pages/styles.js')
const { View, TouchableHighlight, Text } = ReactNative;

class ListItem extends Component {
  render() {
    return (
      <TouchableHighlight onPress={this.props.onPress}>
        <View style={styles.li}>
          <Text style={styles.liTextName}>{this.props.item.name}</Text>
          <Text style={styles.liText}>{this.props.item.title}</Text>
        </View>
      </TouchableHighlight>
    );
  }
}

module.exports = ListItem;

Step 13:- app/components/StatusBar.js

'use strict';
import React, {Component} from 'react';
import ReactNative from 'react-native';
const styles = require('../pages/styles.js')
const { StyleSheet, Text, View} = ReactNative;

class StatusBar extends Component {
  render() {
    return (
      <View>
        <View style={styles.statusbar}/>
          <View style={styles.navbar}>
            <Text style={styles.navbarTitle}>{this.props.title}</Text>
          </View>
        </View>
    );
  }
}

module.exports = StatusBar;

Step 14:- app/components/messageInput.js

'use strict';

import React, {Component} from 'react';
import ReactNative from 'react-native';
const styles = require('../pages/styles.js')
const constants = styles.constants;
const { StyleSheet,TextInput, Text, View, TouchableHighlight} = ReactNative;

class ActionButton extends Component {
  render() {
    return (
      <View style={styles.msgContainer}>
        <View>
          <TextInput
            style={styles.msgInputField}
            onChangeText={this.props.onChangeText}
            value={this.props.value}
            placeholder={"Enter your name"}
          />
       </View>
       <TouchableHighlight
         underlayColor={constants.actionColor}
         onPress={this.props.onPress}
        >
         <View style={styles.ActionButton}>
           <Text style={styles.actionText}>{this.props.title}</Text>
         </View>
     </TouchableHighlight>
    </View>
   );
  }
}

module.exports = ActionButton;

Feel free to comment if you have any issue.

Sunil Yadav

About Sunil Yadav

Hi, This is Sunil Yadav, I am full stack dev. I have a passion for learning and sharing my knowledge with others as publicly as possible.

View all posts by Sunil Yadav →

Leave a Reply

Your email address will not be published. Required fields are marked *