King Somto
19 Jul 2021
•
5 min read
In this article, we will create a group chat application with React and Firebase to let anonymous people join a group chat and send messages. This project will be expanded upon in the upcoming articles so make sure to keep an eye on our blog!
Firebase is a platform owned by Google and used to develop mobile and web applications it also provides some backend services (Firebase cloud functions). It is fully hosted by Google and significantly reduces development time.
There is really no limit in the types or quality of apps that can be built on firebase since it has support for a lot of platforms and technologies, firebase provides SDK for the Android and IOS platforms with growing support for the web and languages like C++, etc.
Personally, I do find firebase useful for building chat-like apps because it supports events that alert all clients when data has been changed.
This article isn't meant to be for getting down at setting up firebase but for developing the app, but if you don't know how to get that done please do check out this article over here
Make sure you have node's latest version installed
[Node latest version] (https://nodejs.org/)
And that's it, not much there
Our first step would be to set up the React app
npx create-react-app chatapp && cd chatapp && npm run start
Installing firebase dependencies
npm install --save firebase
This installs firebase into our app now let's get down to development.
npm install --save styled-components
This installs styled-components into our codebase, in case you don't know styled-components, it's a library I love for styling components in React its a must use for me.
So we are going to start with the component for the message Box
Create a folder called Components this would hold all our component files
mkdir components
create a file inside the components folder message.jsx and paste.
import React from 'react'
import style from 'styled-components'
export default function Message({data}) {
const {message,sender} = data
const Message = style.div`
min-height: 21px;
max-width: 90%;
min-width: 50%;
width: max-content;
background: ${sender?'pink':'blue'};;
text-align: left;
padding: 10px;
border-radius: 10px;
color: white;
margin: 15px 0;
float: ${sender?'left':'right'};;
`
return (
<Message>
{message}
</Message>
)
}
This component is our message Box component for showing our text.
Next compnent we would create is used for showing all our messages, go to the components folder and create a message.jsx file.
import React from 'react'
import style from 'styled-components'
import Message from './messageBox'
export default function Messages() {
const Messages = style.div`
padding: 20px;
height: calc(100% - 64px);
overflow-y: scroll;
`
const messages = [
{
message:'Hi',
sender:0,
},
{
message:'Hi',
sender:0,
},
{
message:'Have you guys read any of my former articles?'
sender:0,
},
{
message:'Hi',
sender:1,
},
{
message:'Hi',
sender:0,
},
{
message:'Hi',
sender:1,
}
]
return (
<Messages>
{messages.map(( data )=>{
return <Message data={data} />
})}
</Messages>
)
}
This shows all our messages in a list.
Finally, we have our container which would be our final component in our components folder create a container.jsx file
import React from 'react'
import style from 'styled-components'
import Messages from './messages'
export default function Container() {
const Box = style.div`
.chatBox{
background# cccfff;
height:90vh;
width:500px;
margin:5vh auto;
border-radius:10px;
position:relative;
}
.textFooter{
position: absolute;
bottom: 0;
display: inline-flex;
width: 100%;
left: 0;
}
input{
width: -webkit-fill-available;
height: 52px;
border: 0;
padding: 0 10px;
}
button{
width: 60px;
border: 0;
height: 52px;
}
`
return (
<Box>
<div className="chatBox">
<Messages/>
<div className="textFooter">
<input type="text" />
<button>Send</button>
</div>
</div>
</Box>
)
}
The output should be
Now the Ui of our app is done let's create a userId that manages the user identity of the app. We would be letting our users create a user name for the group chat.
We need to set up firebase credentials in the app to make our app have access to the firebase server.
We first create a config file and call that in our app.
mkdir config && touch firebase.js
This creates a firebase config file for us to connect to our firebase service.
import firebase from 'firebase';
firebase.initializeApp({
apiKey: '****',
authDomain: '****',
databaseURL: '****',
client_secret:'****',
projectId: '****',
storageBucket: '****',
messagingSenderId: '****',
client_id:
'****',
appId:'****',
REACT_APP_GOOGLE_CLIENT_ID:
'****',
});
export const db = firebase.database();
Pasting this configures our app credentials for connecting to firebase.
Replace asterisk with your credentials.
Now we have created the firebase connection so we would like to use that instance to connect to our firebase DB.
We need to know who is chatting so we can differentiate other people's messages from ours, we do that by letting users create their anonymous user names and saving that to the DB with the message content. Kinda like this.
So let's create a component that takes in the user's username
Let's create it in our components folder and call it addName.jsx
import React from 'react';
import style from 'styled-components';
export default function EmailAdderComponent( {setName} ) {
const input = React.createRef('');
const EmailAdder = style.div`
width: -webkit-fill-available;
height: 100vh;
position: absolute;
z-index: 2;
background: wheat;
top: 0;
`;
return (
<EmailAdder>
<div className="textContainer">
<p>
Type Your Name
</p>
<input
id="input"
onChange={(e) => {
input.current = `${e.target.value}`;
}}
type="text"
/>
<button
onClick={async (e) => {
if (input.current.length === 0) {
return;
}
setName(input.current)
}}
>
Send
</button>
</div>
</EmailAdder>
);
}
The setName function is passed down from the parent component and is used to set the username variable.
Here we type in our UserName.
Now to make some changes to our parent component app.js file
import Container from './components/container';
import EmailAdderComponent from './components/addName';
import React from 'react';
function App() {
const [name,setName] = React.useState()
return (
<div className="App">
{!name && <EmailAdderComponent setName={setName} />}
{name && <Container name={name} />}
</div>
);
}
export default App;
In our app.js file, we check if our name variable has been set if it has been then we render the
Now we let's make some edits to the messagesfile.jsx
***
import { db } from '../config/firebase';
***
****
React.useEffect(() => {
db.ref('chats').on('value', (snapShot) => {
let chats = [];
snapShot.forEach((snap) => {
chats.push(snap.val());
});
setMessages(chats);
var element = document.getElementById('messages');
element.scrollTop = element.scrollHeight - element.clientHeight;
});
}, []);
****
This adds an event listener to the component and checks for changes in the chats collection we then render the messages from the message list.
Now we make changes to the button of our container.jsx
****
import { db } from '../config/firebase';
****
const input = React.createRef('');
return (
<Box>
<div className="chatBox">
<Messages name={name} />
<div className="textFooter">
<input
id="input"
onChange={(e) => {
input.current = `${e.target.value}`;
}}
type="text"
/>
<button
onClick={async (e) => {
if (input.current.length===0) {
return
}
document.getElementById('input').value = '';
await db.ref('chats').push({
message: input.current,
sender: name,
});
input.current = ''
}}
>
Send
</button>
</div>
</div>
</Box>
);
}
****
Then onClick function gets the text from the input command and pushes it into the firebase chats collection along with the user name.
Testing the component we can see that the chat is updated once we click on the send button.
But next, we need the scroll to a position at the end whenever we send a message
****
var element = document.getElementById('messages');
element.scrollTop = element.scrollHeight - element.clientHeight;
input.current = ''
****
Now our scroll navigates to the bottom whenever we send a message and we can see our latest message sat the bottom.
Building React chat apps for firebase chats is pretty straightforward using the firebase database because of the functionalities it provides, and the value event for collections we can watch for changes in the collection and passes the changes to the app state.
Firebase lets you perform lots of database functionalities without actually creating a database which means faster development time.
Ground Floor, Verse Building, 18 Brunswick Place, London, N1 6DZ
108 E 16th Street, New York, NY 10003
Join over 111,000 others and get access to exclusive content, job opportunities and more!