DEV Community

Emerson Vieira
Emerson Vieira

Posted on

Chat com React Native e Firebase

Antes de mais nada, iremos usar partes de dois tutoriais que já disponibilizei.
1) Siga o tutorial do link abaixo a partir da parte que contém os prints da tela do Android Studio. Esse passo requer que você já tenha seu projeto criado e rodando.
Login com Google usando React Native
2) Siga todo o tutorial do link abaixo. No final vou disponibilizar as modificações feitas no arquivo deste tutorial, mas é importante seguir o passo a passo.
Login com LinkedIn usando React Native

Acesse o console do firebase da sua conta, abra seu projeto criado especialmente para este tutorial. No menu lateral, acesse Database, em seu Cloud Firestore crie uma coleção chamada groupChat.

Alt Text

Outra coisa importante para essa parte do firebase é que você adicione um app android e outro app web ao seu projeto. A imagem abaixo mostra onde fica essa opção.

Alt Text

Alt Text

Ao selecionar android, irá aparecer uma outra página para que você possa preencher os dados necessários, onde a chave SHA1 obtida no passo 1 será preenchida. Ao final é disponibilizado um arquivos chamado google-services.json que você precisa salvar na pasta app que fica dentro da pasta android de seu projeto. A imagem abaixo mostra como é a página em questão.

Alt Text

Ao selecionar web, irá abrir uma página para que você preencha alguns dados e o mais importante nessa parte é copiar os dados que serão disponibilizados pelo firebase ao final. Copie e salve os dados disponibilizados. A imagem abaixo mostra como é a página.

Alt Text

Em seu projeto, crie um arquivo chamado firebaseSDK.js e dentro dele você vai colocar os dados obtidos no passo anterior. Abaixo um exemplo do arquivo:

import firebase from  '@react-native-firebase/app';

const config = {

apiKey:  '*****',

authDomain:  '*****',

databaseURL:  '*****',

projectId:  '*****',

storageBucket:  '******',

messagingSenderId:  '*****',

appId:  '******',

};

let Firebase;

if (!firebase.apps.length) {

Firebase = firebase.initializeApp(config);

}

export  default Firebase;
Enter fullscreen mode Exit fullscreen mode

Iremos precisar de duas dependências para a parte do Firebase em nosso projeto. A instalação e configuração de cada uma é mostrada nos links que irei disponibilizar abaixo:
1) https://invertase.io/oss/react-native-firebase/quick-start/existing-project
2) https://invertase.io/oss/react-native-firebase/v6/firestore/quick-start

Observação: No passo 1 acima, há uma configuração para android e iOS, recomendo que dê uma olhada para que tudo ocorra bem. Caso use apenas android, como é no meu caso, siga apenas a parte de configuração para android.

Neste tutorial também é usado outra dependência, ela será útil para a navegação usada no tutorial. Navegue até a raiz do seu projeto pelo terminal e digite o comando abaixo:

$ yarn add react-navigation
Enter fullscreen mode Exit fullscreen mode

Para a parte do chat iremos usar uma lib bastante famosa para esta finalidade. A lib se chama Gifted Chat e para adicionar a mesma em seu projeto, acesse a raiz do seu projeto pelo terminal e digite o comando abaixo:

$ yarn add react-native-gifted-chat
Enter fullscreen mode Exit fullscreen mode

Agora irei disponibilizar o código dos arquivos referentes ao Login e Chat em si. Abaixo o código de Login com LinkedIn com algumas alterações para este tutorial. Neste tutorial o chamei de Main.

Main.js

import React, {useState, useEffect} from  'react';

import {StyleSheet, View, Text, Image} from  'react-native';

import LinkedInModal from  'react-native-linkedin';

import axios from  'axios';

const styles = StyleSheet.create({

container: {

flex:  1,

backgroundColor:  '#fff',

justifyContent:  'center',

alignItems:  'center',

},

});

export  default  function  Main({navigation}) {

const [token, setToken] =  useState('');

const [info, setInfo] =  useState();

const [loading, setLoading] =  useState(true);


const instance = axios.create({

baseURL:  'https://api.linkedin.com/v2',

headers: {

Authorization:  'Bearer  '  + token,

},

});

async  function  getInfo() {

await instance

.get(

'/me?projection=(id,firstName,lastName,profilePicture(displayImage~:playableStreams))',

)

.then(response => {

setInfo(response.data);

setLoading(false);

navigation.navigate('Chat', {

userChat: response.data,

});

})

.catch(error =>  console.log(error));

}

useEffect(() => {

getInfo();

}, [token]);

const renderData = info && (

<>

<Text>{info.firstName.localized.pt_BR}</Text>

<Text>{info.lastName.localized.pt_BR}</Text>

<Image

source={{

uri:

info.profilePicture['displayImage~'].elements[3]['identifiers'][0][

'identifier'

],

}}

style={{

width:  200,

height:  200,

left:  'auto',

right:  'auto',

justifyContent:  'center',

}}

/>

</>

);

return (

<View  style={styles.container}>

<LinkedInModal

clientID="******"

clientSecret="*****"

redirectUri="https://api.linkedin.com/v2/me"

onSuccess={token =>  setToken(token.access_token)}

onError={error =>  console.log(error)}

areaTouchText={{top:  20, bottom:  20, left:  150, right:  150}}

/>

{loading && <Text>{'Loading...'}</Text>}

{renderData}

</View>
);

}

Main.navigationOptions = {

title:  'Main',

};
Enter fullscreen mode Exit fullscreen mode

Agora o código do Chat.js

import React, {useState, useEffect} from  'react';

import {View, Text} from  'react-native';

import firestore from  '@react-native-firebase/firestore';

import {GiftedChat, Bubble} from  'react-native-gifted-chat';

function  Chat(props) {

const [user, setUser] =  useState(props.navigation.getParam('userChat'));

const [messages, setMessages] =  useState([]);

useEffect(() => {

console.log(user);

const db =  firestore();

db.collection('groupChat')

.orderBy('createdAt', 'desc')

.onSnapshot(function(doc) {

let receivedMessages = [];

doc.docs.map(doc => {

receivedMessages.push({

_id: doc.id,

...doc.data(),

});

});

setMessages(GiftedChat.append(messages, receivedMessages));

});

}, [user]);



function  onSend([messages]) {

firestore()

.collection('groupChat')

.add(messages);

}

function  renderBubble(props) {

return (

<View>

<Text  style={{left:  90}}>{props.currentMessage.user.name}</Text>

<Bubble

{...props}

/>

</View>

);

}

return (

<GiftedChat

dateFormat={'DD-MM-YYYY'}

timeFormat={'h:mm'}

renderBubble={renderBubble}

messages={messages}

onSend={messages =>  onSend(messages)}

user={{

id: user.id,

name: user.firstName.localized.pt_BR,

}}

/>

);

}

Chat.navigationOptions = {

title:  'Chat',

};

export  default Chat;
Enter fullscreen mode Exit fullscreen mode

E por último o código de rotas

routes.js

import {createAppContainer, createSwitchNavigator} from  'react-navigation';

import Main from  './Main';
import Chat from  './Chat';

const Routes =  createAppContainer(
createSwitchNavigator({
Main: Main,
Chat: Chat,
}),
);

export  default Routes;
Enter fullscreen mode Exit fullscreen mode

O Chat em questão funciona como uma sala única para várias pessoas. Abaixo segue imagens do app em funcionamento e como deve ficar:

Alt Text

Alt Text

Alt Text

Alt Text

É isto! Esse é bem mais trabalhoso, mas creio que deu para passar +/- como é e espero que consigam seguir o tutorial e funcione direitinho :) se surgir dúvidas é só comentar. Até a próxima :)

Top comments (3)

Collapse
 
oliveiradiney profile image
oliveiradiney

Quando há dois dispositivos com horários diferentes, as mensagens não são enviadas em ordem. O aparelho com o horário mais adiantado no seu celular sempre tem a última mensagem e o aparelho que tem o horário atrasado sempre tem o horário antes da mensagem do outro aparelho, mesmo enviando depois do outro aparelho.

Como fazer com que as mensagens estejam em ordem independente do tempo em diferentes dispositivos?

Collapse
 
dxdns profile image
Diógenes Rodrigues

Da pra utilizar esse método para criar um chat privado?

Collapse
 
mensonones profile image
Emerson Vieira

Dá sim :)