Stream's Messaging API allows you to build real-time chat applications that are scalable, fault-tolerant, secure, and fast, so you don’t have to re-invent the wheel by starting from scratch. You’ll take less time to create a robust app (like days to create a real-time chat application with Stream instead of months)!.
By the end of this tutorial, you should have a functional chat application with in-app messaging. In-app messaging allows you to engage users who are actively using your mobile app by sending them content that will encourage them to take action or keep them informed.
Let's create a chat app to which we’ll add in-app messaging. We'll also want our app to send an in-app message to everyone in the chat group when someone sends a message to the group.
Prerequisites
To follow along with this post, ensure sure that you’ve installed the following:
Note that you’ll need a macOS, with XCode installed to run the iOS emulator.
React Native is a mobile app application development framework that allows you to build a multi-platform mobile application — Android and iOS.
That means at the end of this tutorial; you will have an app with in-app messaging that you can deploy for both android and iOS devices.
Setting Up
First of all, let’s set up a react native application with Expo. Run the following command to install expo-cli
:
1$ npm install -g expo-cli
Then, run the following command to create a project and install all the dependencies required for Stream to work with React Native and Expo projects:
12345$ expo init -t blank --name cool-chat-app && cd cool-chat-app $ yarn add stream-chat-expo react-navigation@4.1.0 react-navigation-stack@2.1.0 $ expo install @react-native-community/netinfo@4.6.0 react-native-gesture-handler@1.5.6 react-native-reanimated@1.4.0 react-native-screens@2.0.0-alpha.12 react-native-safe-area-context@0.6.0 @react-native-community/masked-view@0.1.5 react-native-in-app-notification metro-react-native-babel-preset
Once those are installed, you can use the following command to create a components
directory (where we’ll put all our components) and a Chat.js
component file within it:
1mkdir components && touch components/Chat.js
Your app structure should look like this after running the command above:
.
├── App.js
├── app.json
├── assets
│ ├── icon.png
│ └── splash.png
├── babel.config.js
├── components
│ └── Chat.js
├── package.json
├── web-build
│ └── register-service-worker.js
└── yarn.lock
Next up, let’s add Stream Chat to the app!
Registering on the Stream Website
Setting up a Stream Chat account is simple — head over to the Stream website and register with your Github account or with your email address.
Once your registration is complete, head over to your dashboard, where you will find your API credentials (API_KEY, SECRET and APP_ID), as shown in the image below:
Keep this information in a secure place; you’ll need it to authenticate with the Stream API/SDK as we proceed.
Getting Started
Let’s get into the code!
Create a .env
file in the root of the directory and add the APP_KEY
you got from the dashboard:
API_KEY=<YOUR_API_KEY>
Open your ./babel.config.js/
and add the code below to the presets:
'module:metro-react-native-babel-preset', 'module:react-native-dotenv',
Doing so will allow us to import our environment variables from the .env
file:
module.exports = function(api) { api.cache(true); return { presets: [ 'babel-preset-expo', 'module:metro-react-native-babel-preset', 'module:react-native-dotenv' ] }; };
Open the /Component/Chat.js
file we created initially, and add the following content to it:
import React, { Component } from 'react'; import { View, Text, StyleSheet, SafeAreaView } from 'react-native'; import { withInAppNotification } from 'react-native-in-app-notification'; import { API_KEY } from 'react-native-dotenv'; import { StreamChat } from 'stream-chat'; import { Chat, Channel, MessageList, MessageInput } from 'stream-chat-expo'; const chatClient = new StreamChat(API_KEY); const userToken = API_TOKEN; const user = { id: 'green-heart-8', name: 'Green heart', image: 'https://stepupandlive.files.wordpress.com/2014/09/3d-animated-frog-image.jpg' }; chatClient.setUser(user, userToken); class ChatScreen extends Component { render() { const channel = chatClient.channel('messaging', 'green-heart-8'); channel.watch(); channel.on('message.new', event => { const message = channel.state.messages[channel.state.messages.length - 1]; if (message.user.id !== chatClient.user.id) { this.props.showNotification({ title: 'Stream Notification', message: `${message.user.name} says: ${message.text}` }); } }); return ( <SafeAreaView> <Chat client={chatClient}> <Channel channel={channel}> <View style={{ display: 'flex', height: '100%' }}> <MessageList /> <MessageInput /> </View> </Channel> </Chat> </SafeAreaView> ); } } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center' } }); export default withInAppNotification(ChatScreen);
Let’s explain what is going on here...
Here, we import the in-app messaging notification package we intend to use to show the app messaging:
import { withInAppNotification } from 'react-native-in-app-notification';
Then, we import Stream and the Stream Chat Components we want to use for this app:
import { StreamChat } from 'stream-chat'; import { Chat, Channel, MessageList, MessageInput } from 'stream-chat-expo';
Next, we initialize a new Stream Client, and then set a user
:
const chatClient = new StreamChat(API_KEY); const userToken = API_TOKEN; // you can retrieve this from the backend server const user = { id: 'green-heart-8', name: 'Green heart', image: 'https://stepupandlive.files.wordpress.com/2014/09/3d-animated-frog-image.jpg' }; chatClient.setUser(user, userToken);
You’ll need to retrieve the token from an API endpoint; you can check out this open-source API for Stream that you can use right off the bat to get authenticated!
All you need to do is clone the repo:
1$ git clone https://github.com/astrotars/stream-chat-api.git
run the command:
1$ npm install
Then, add your API KEY
and API SECRET
to the .env
file of the project and you can send a post request with the details of the user you want to authenticate as a JSON object to the endpoint http://localhost:8080/v1/auth/init
, like so:
{ "name": { "first": "First Name", "last": "Last Name" }, "email": "foo@bar.baz", "password": "qux" }
This should return to you a token
, which you can use to set the User
. You can generate this token
like in a login page:
chatClient.setUser(user, userToken);
Then, in the ChatScreen
component’s render method, create a channel with the type "messaging
" and give it any title you'd like; we’ll call ours golf-club
. Next, call the watch()
method on the channel client so that you can monitor the activities on the channel:
const channel = chatClient.channel('messaging', 'golf-club'); channel.watch();
In the following section, we subscribe to the channel’s new message
event, then check if the message is not from you. If that’s true, we show a notification, using the props
from the react-native-in-app-messaging
package (the title of the message and the actual message body).
channel.on('message.new', event => { const message = channel.state.messages[channel.state.messages.length - 1]; if (message.user.id !== chatClient.user.id) { this.props.showNotification({ title: 'Stream Notification', message: `${message.user.name} says: ${message.text}` }); } });
Notice we are not sending the in-app message to ourself, because it doesn’t make sense to send a notification to ourselves when we send a message.
Right here:
const message = channel.state.messages[channel.state.messages.length - 1];
We are getting the last message object that was sent to the channel, and broadcasting it to every member of the channel as an "in-app message".
To get the in-app messaging plugin to work correctly with our app, let’s wrap our component with the withInAppNotification
HOC we imported initially, like so:
export default withInAppNotification(ChatScreen);
Also, we need to add it to our app component in the App.js
file:
import React, { Component } from 'react'; import { InAppNotificationProvider } from 'react-native-in-app-notification'; import Chat from './components/chat'; export default class App extends Component { render() { return ( <InAppNotificationProvider> <Chat /> </InAppNotificationProvider> ); } }
Finally, let’s return
the Stream Chat components, as shown below:
return ( <SafeAreaView> <Chat client={chatClient}> <Channel channel={channel}> <View style={{ display: 'flex', height: '100%' }}> <MessageList /> <MessageInput /> </View> </Channel> </Chat> </SafeAreaView> );
This is all we need to get our app with in-app messaging working!
Here is a demo of what we’ve built so far:
Wrapping Up
There is so much you can do with Stream Chat! I encourage you to look at the docs to find more amazing features of Stream Chat that you can add to the app.
We'll be excited to see what you’ll build with Stream Chat!
Looking for the complete source code? It’s on GitHub!
Happy coding!