Build a chat app with React Native and Gifted Chat

  • Farid Safi
May 30th, 2018
To follow this tutorial you will need Node, npm and the React Native CLI. Some knowledge of mobile development with React Native will be helpful.

This tutorial will show you how to build your own realtime Android and iOS chat using React Native, Gifted Chat and Pusher Chatkit.

Create a new project

Start out by creating an empty React Native project using react-native init (make sure you have react-native-cli installed first). We’ll call it it GiftedChatWithChatkit:

    react-native init GiftedChatWithChatkit

Once you have the project, go inside it with:

    cd GiftedChatWithChatkit

Install modules

Now, you are going to need two modules:

  1. @pusher/chatkit
  2. react-native-gifted-chat

In order install them in your project, write following commands:

    npm install @pusher/chatkit react-native-gifted-chat --save

Start with non-realtime chat

Let's try to implement basic chat. Create a new file called MyChat.js in the root folder with the following code:

    import React from "react";
    import { GiftedChat } from "react-native-gifted-chat";

    export default class MyChat extends React.Component {
      state = {
        messages: []
      };

      componentDidMount() {
        this.setState({
          messages: [
            {
              _id: 1,
              text: "I think we passed the first step of the tutorial. We will now need a Pusher account!",
              createdAt: new Date(),
              user: {
                _id: 1,
                name: "React Native",
                avatar: "https://placeimg.com/140/140/any"
              }
            }
          ]
        });
      }

      render() {
        return <GiftedChat messages={this.state.messages} />;
      }
    }

And replace the existing code in App.js with

    import React, { Component } from "react";
    import MyChat from "./MyChat";

    export default class App extends Component {
      render() {
        return <MyChat />;
      }
    }

Now try running your app with react-native run-ios or react-native run-android (depending if you want to run in iOS or Android) to see a basic chat module with an initial chat message bubble:

Get a Pusher Chatkit account

Now that you have set up your project with modules, you need a Pusher account.

It's a very simple process. Simply go to pusher.com/chatkit and sign up for the public beta. You can do so using your Google account, GitHub account or regular email and password.

Once you have signed up, you will be redirected to the dashboard.

Here, you need click on the CREATE button below Chatkit. A dialogue box will appear asking you to give your instance a name (for example, MyFirstChat). When you are done, click CREATE and you have your first Chatkit instance ready.

You can find the instance on the left menu bar of the dashboard. If you go into the dashboard of the app, you will find several tabs pertaining to the Chatkit instance. For this sake of this tutorial, we won't be needing all of them.

Start by exploring your keys section. You will find your Instance Locator here, along with Secret Key.

You will be needing them when we back to coding.

Next, go to the TEST TOKEN PROVIDER section. You will find the test token provider here. By default it is disabled. But for our testing we will need it, so enable it. You will see an endpoint for test token provider show up.

Next up, INSTANCE INSPECTOR.

This is the home of the trinity of Chatkit. The user. The room. The message

Basically, every user has to be in at least one room and every room needs to have at least one user. If you satisfy this, you will be able to send and receive messages for the user-room pair. So, let's try doing that.

For the purpose of this example we will use the following room-user pair. Let's call the user: Dave and the room: DiscoveryOne

Implement the Chatkit API

Back to code now!

In your MyChat.js component (that we just created), import the Chatkit module:

    import Chatkit from "@pusher/chatkit";

Add the needed constants above the class declaration:

    const CHATKIT_TOKEN_PROVIDER_ENDPOINT = "<url from TEST TOKEN PROVIDER section>";
    const CHATKIT_INSTANCE_LOCATOR = "<id from CREDENTIALS section>";
    const CHATKIT_ROOM_ID = "<room identifier from INSTANCE INSPECTOR section>";
    const CHATKIT_USER_NAME = "<user name>"; // Let's chat as "Dave" for this tutorial

And replace the current componentDidMount function:

    componentDidMount() {
      // This will create a `tokenProvider` object. This object will be later used to make a Chatkit Manager instance.
      const tokenProvider = new Chatkit.TokenProvider({
        url: CHATKIT_TOKEN_PROVIDER_ENDPOINT
      });

      // This will instantiate a `chatManager` object. This object can be used to subscribe to any number of rooms and users and corresponding messages.
      // For the purpose of this example we will use single room-user pair.
      const chatManager = new Chatkit.ChatManager({
        instanceLocator: CHATKIT_INSTANCE_LOCATOR,
        userId: CHATKIT_USER_NAME,
        tokenProvider: tokenProvider
      });

      // In order to subscribe to the messages this user is receiving in this room, we need to `connect()` the `chatManager` and have a hook on `onNewMessage`. There are several other hooks that you can use for various scenarios. A comprehensive list can be found [here](https://docs.pusher.com/chatkit/reference/javascript#connection-hooks).
      chatManager.connect().then(currentUser => {
        this.currentUser = currentUser;
        this.currentUser.subscribeToRoom({
          roomId: CHATKIT_ROOM_ID,
          hooks: {
            onNewMessage: message => alert(message.text)
          }
        });
      });
    }

Here we have hooked a room subscriber to be trigger dynamically on an incoming message event (onNewMessage). It will fire an event that alerts the data coming from Pusher’s trigger.

Send a message to test

Wanna test it? There are several ways to send a message to a user in any given room. You can create a backend server in any of the wide range of frameworks supported by Pusher Chatkit and use the sendMessage function. Or you can send it from a the INSTANCE INSPECTOR section of the dashboard itself.

So let's go back there and open the INSTANCE INSPECTOR section. There you will find fields to input the name of user, room and a text message.

Create a new user called HAL9000 for the room DiscoveryOne and send the message Good morning, Dave.

At this point, you should find an alert on your emulator showing the data that you just sent.

Make it real!

But we want this message to be integrated with our Gifted Chat module, right? We want any incoming message to show as a message in out chat window. Let's see how we can pull that off.

We can create a method, say onReceive, and make it handle the incoming data such that whenever there is a new message from the room DiscoveryOne and user HAL9000 it would append it to the existing chat window.

    onReceive(data) {
      const { id, senderId, text, createdAt } = data;
      const incomingMessage = {
        _id: id,
        text: text,
        createdAt: new Date(createdAt),
        user: {
          _id: senderId,
          name: senderId,
          avatar: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQmXGGuS_PrRhQt73sGzdZvnkQrPXvtA-9cjcPxJLhLo8rW-sVA"
        }
      };

      this.setState(previousState => ({
        messages: GiftedChat.append(previousState.messages, incomingMessage)
      }));
    }

This onReceive method looks good but we need to bind it with our existing event subscriber. So instead of alerting the data, let's pass the data to this function.

We can do so by simply replacing alert and writing onReceive instead.

Replace:

    onNewMessage: message => alert(message.text)

With:

    onNewMessage: this.onReceive.bind(this)

The final step will be to send messages directly from the chat window. Let's now add the Pusher sendMessage feature :

    onSend([message]) {
      this.currentUser.sendMessage({
        text: message.text,
        roomId: CHATKIT_ROOM_ID
      });
    }

Connect the new onSend function with Gifted Chat:

    render() {
      return (
        <GiftedChat
          messages={this.state.messages}
    +     onSend={messages => this.onSend(messages)}
    +     user={{
    +       _id: CHATKIT_USER_NAME
    +     }}
        />
      );
    }

And voila! You have your own realtime chat built with React Native using Gifted Chat and Pusher Chatkit.

Further reading

The Pusher ecosystem offers several realtime solutions. You can find more documentation details here.

Chatkit is also supported on other frameworks for client-side:

And on the server-side:

You can find the code for this tutorial on GitHub.

  • Chatkit

© 2018 Pusher Ltd. All rights reserved.

Pusher Limited is a company registered in England and Wales (No. 07489873) whose registered office is at 160 Old Street, London, EC1V 9BW.