How to build a chat app using React Native and Hooks
Tags: reactnative, chat, api, sdk
Published: 2021-11-10 06:28:55

---
title: How to build a chat app using React Native and Hooks
published: True
date: 2021-10-08 20:09:31 UTC
tags: ReactNative,chat,API,SDK
canonical_url: https://sendbird.com/developer/tutorials/react-native-chat-tutorial
cover_image: https://sendstage.wpengine.com/wp-content/uploads/Get-started_How-to-build-a-chat-app-using-React-Native.png
---

By Walter Rodriguez
Solutions Engineer | [Sendbird](https://www.sendbird.com)

*The post [How to build a chat app using React Native and Hooks](https://sendbird.com/developer/tutorials/react-native-chat-tutorial) appeared first on [Sendbird](https://sendbird.com).*

#Introduction

This tutorial will show you how to build a messaging app using React Native. First, we’ll set the stage for this tutorial by understanding why you should use React Native in the first place. Then we’ll explain React Native Hooks functions before diving into the implementation details of how to build a chat application with Sendbird and React Native. 

Please note that this tutorial assumes a basic understanding of React Native.

With this in mind, let’s begin.

###Why React Native?

Most applications today are built natively, but there are also hybrid applications developed using Webviews. The properties and features of Webviews introduce limits to applications in comparison to their native counterparts, however. Applications using Webviews are also relatively slower than native applications. React Native allows to bridge this gap by providing applications access to native functionality and properties.

React Native does this by separating the JavaScript code and native code into different threads. It also enables asynchronous communication between the two, which boosts the overall app performance. Moreover, since React Native uses JavaScript, developers unfamiliar with native applications can use their existing knowledge and experience to reduce coding time.

###Who is using React Native?

Because of its advantages of code reusability, reliability, robustness, and the existence of a helpful community, many companies, from established Fortune 500 companies to high-growth startups, develop applications with React Native. Some well-regarded organizations using React Native include Instagram, Shopify, Tableau, Tesla, UberEats, and Skype.

Now that we have understood the basics let’s move on to React Native Hooks functions. 

###What are React Native Hooks functions?

Hooks are functions that let you “hook” into React states and lifecycle features from function components. Hooks don’t work inside classes — they let you use React without classes. (We don’t recommend rewriting your existing components overnight, but you can start using Hooks in the new ones if you’d like.)

React provides a few built-in Hooks such as useState. You can also create your own Hooks to reuse stateful behavior between different components. Let’s look at the built-in Hooks first.

For more information about Hooks, check out the [react site](https://reactjs.org/docs/hooks-overview.html).

Now let’s understand how to work with Sendbird and Hooks for your chat application. This tutorial is composed of nine more parts:

1. Installing React Native
2. Downloading the Sendbird sample 
3. Debugging
4. Understanding the folder structure
5. Building the Login component
6. Building the Channels List component
7. Building the Messages component
8. Sending and receiving messages
9. Other Sendbird features

#Step 1. Installing React Native to build chat

You need to have the **React Native CLI** to work with this example. Please install globally:

```
npm install -g react-native-cli
```
You can quickly check that the installation finished correctly by showing the version number:

```
react-native --version
```

#Step 2. Downloading the Sendbird sample

Once you have the React Native CLI installed, you can download the sample code. First clone the repository:

```
git clone https://github.com/sendbird/SendBird-JavaScript.git
```
Then, open the following folder using your favorite IDE: 

```
./SendBird-JavaScript/react-native-hook-sample/Sendbird
```
As the next step, let’s install all the dependencies. Run the following command: (it takes some time to download all packages)

```
npm i
```
You can run this either for Android or iOS. Open the package.json file and check the scripts we have for you to use:

![Scripts to run the Android and iOS versions
](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iqhqh2x8mhom6i2ebrhl.png) <center>*Scripts to run the Android and iOS versions*</center><br>

To run Android, just type:
```
npm run android
```

###Troubleshooting Android
If you have problems running the Android version, you can try the following:

* If you run on an actual device, check if everything is installed – especially Android studio.
* Check if your device is visible by adb devices; sometimes, it may not work or have lags. In this case, call adb kill-server and then adb start-server.
* You might want to build the project using react-native run-android. If it fails, you might need to run it with Android studio.
* Make sure your ANDROID_HOME is in the path. Something like:
```
export ANDROID_HOME=/Users/[your user]/Library/Android/sdk 
``` 
For iOS, you need to install Pods once:
```
cd ios
pod install
pod update
```
This will install all the libraries to run the iOS version.

###Troubleshooting iOS
If you have problems running the iOS version, you can try the following:

* Do a pod update and then pod install from inside the ios/ folder.
* Delete the ios/build folder.
* It is better not to change any build phases, rules, or settings in XCode as this may cause further issues.
* It is better not to update the packages listed in the package.json file or the ones inside ios/Pods. This is because these are the versions used in our testing.

###Troubleshooting for both platforms

* Make sure you are not running any VPN. Sometimes this creates problems.
* If you have a React Native terminal window running, try closing it and run the command above again.
* You can run npm run clean from the root directory. This will clean old builds.
* You can delete the file **package-lock.json**, and try running npm i again, but we do not recommend this because of compatibility issues.

Check the list of prerequisites before running this sample. You can find them [here](https://reactnative.dev/docs/getting-started).

#Step 3. Debugging your React Native chat app
From your iOS simulator, you can debug the application and see console outputs to Chrome. Press **Command + D** to see a screen like below:
![Debugging from iOS screen](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k4ktl5i51z1xr00tymcf.png)<center>*Debugging on iOS*</center><br>

When you click Debug in Chrome, a Chrome window will open. Use the Chrome developer tools to monitor the outputs written by **console.log()**.

#Step 4. Understanding the folder structure

The following is a description of the most important files and folders for this sample application.

####package.json

This file contains all the packages this project will use. Because of compatibility issues, we recommend not changing the version of these packages.

![Dependencies for this sample application
](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ntw1zmws8i9wwvf5fbaz.png)<center>*Dependencies for this sample application*</center><br>

The file also contains the scripts you can run:
![Code showing the scripts you can run](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/38jcndcvzshh9ptkhiyi.png)<center>*Scripts you can run*</center><br>

Run npm run android to launch the Android version.

Run npm run ios to launch the iOS version.

Run npm run clean to clear any previous build.

####node_modules

This folder contains all the downloaded libraries this project will use. This folder is created every time you run npm i.

####android

This folder contains all the files for an Android project. You can use Visual Studio to open and run the project.

####iOS
This folder contains all the files for the iOS project. You can open it with Xcode.

####src
This folder contains all the Javascript files for our demo application.

####index.js
This is the first file to be executed by React Native.

{% gist https://gist.github.com/warodri-sendbird/99216f6e02b28cba5b014c7fc5f66508 file=index.js %}

[Gist](https://gist.github.com/warodri-sendbird/99216f6e02b28cba5b014c7fc5f66508)

We define which function will process the information when we receive a Push message, for Android devices. In this example, the function **onRemoteMessage** will do the work. It is inside the **./src/utils utils.js** file. 

####App.js

This file is called from the file **index.js**. It shows the first screen we see when users run our application.

You will see where your Sendbird application ID (you can get this from your [Sendbird Dashboard](https://dashboard.sendbird.com/auth/signin)) is defined:

{% gist https://gist.github.com/warodri-sendbird/4d83e7a1080c3c0e965dd301b89aca06 file=sendbirdapp.js %}

[Gist](https://gist.github.com/warodri-sendbird/4d83e7a1080c3c0e965dd301b89aca06)

We are now ready to initialize the Sendbird SDK. At this point, we are not connected.

{% gist https://gist.github.com/warodri-sendbird/8f1f596ebb7de6a87f90c65812ba54f2 file=init-sendbird.js %} 

[Gist](https://gist.github.com/warodri-sendbird/8f1f596ebb7de6a87f90c65812ba54f2)

We will use our first Hook to ask permission to receive notifications. 

If we already have a token from Firebase, we use the Sendbird function **registerAPNSPushtokenForCurrentUser** to register it for an **iOS** device and **registerGCMPushTokenForCurrentUser** for an **Android** device.

{% gist https://gist.github.com/warodri-sendbird/1b0c544d1ff592d8b26b696e2850e0db file=App.js %}

[Gist](https://gist.github.com/warodri-sendbird/1b0c544d1ff592d8b26b696e2850e0db)

View a detailed [tutorial](https://sendbird.com/docs/chat/v3/javascript/guides/push-notifications#1-push-notifications) about implementing Firebase for React Native. 

The next step is to define our Stack Navigator. A Stack Navigator provides a way for your app to transition between screens. Each new screen can be placed on top of a stack.

By default, the stack navigator offers a familiar iOS and Android look and feel. New screens slide in from the right on iOS, and the default OS animation is used on Android. You can customize the animations to match your needs.<br>

{% gist https://gist.github.com/warodri-sendbird/6be5418dea0d8c81625c4024dba8b9ec file=App - View.js %}

[Gist](https://gist.github.com/warodri-sendbird/6be5418dea0d8c81625c4024dba8b9ec)

#Step 5. Building the Login component for your React Native chat app

![Login window](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0mfpmhjx4taujqzrjdjf.png)<center>*Login window*</center><br>

The Stack Navigator will **Lobby** first. This file is in **./src/page/lobby.js**.

Many Hooks are applied here, and the principal actor is **currentUser**. Because it depends on the user previously signed, we will show a login screen or the list of [chat channels](https://sendbird.com/docs/chat/v3/javascript/guides/channel-types).

This sample uses **AsyncStorage** to read (and save) the value of a previously signed user. If there’s a value, we read it and define that the user as initialized.

{% gist https://gist.github.com/warodri-sendbird/bff4a3458cb6be6de00fb5305685e44c file=Lobby - Check saved user.js %}

[Gist](https://gist.github.com/warodri-sendbird/bff4a3458cb6be6de00fb5305685e44c)

We build the screen accordingly. If we have a signed user, we show the **Channels** component. Otherwise, we show the **Login** screen.

{% gist https://gist.github.com/warodri-sendbird/f6170ebfc9a36c9f9f860a8d9f8e879d file=Lobby - Screen.js %}

[Gist](https://gist.github.com/warodri-sendbird/f6170ebfc9a36c9f9f860a8d9f8e879d)

Once the **Login** component responds, the login function executes. We save this value in the **AsyncStorage** and run the token registration for iOS and/or Android to receive [push notifications](https://sendbird.com/docs/chat/v3/javascript/guides/push-notifications#1-push-notifications).

{% gist https://gist.github.com/warodri-sendbird/e772c5f8f490e09d0c4f9e77f095f112 file=Lobby - Logging in.js %}

[Gist](https://gist.github.com/warodri-sendbird/e772c5f8f490e09d0c4f9e77f095f112)

The login screen will paint the screen we see above and wait for the user to click on the **Connect** button.

When clicked, the button calls the connect function connect.

{% gist https://gist.github.com/warodri-sendbird/fcc8910371ee8a1a6b566e1b5caa8be9 file=Login - Connect.js %}

[Gist](https://gist.github.com/warodri-sendbird/fcc8910371ee8a1a6b566e1b5caa8be9)

###Connecting to Sendbird

As you can see, the sendbird.connect(…) function call connects the device with the Sendbird servers via Websockets. If you see any error here, it is because the user ID selected is invalid, your Sendbird application ID is incorrect, the function is not defined, or because you’re not connected to the Internet. 

We suggest you check for any error code and inform your users.

###Foreground and background

You must check if your application goes to the background, for the following screens (channels, messages, etc.). If this happens, then you should invoke setBackgroundState. You will appear as disconnected for the rest of the users. Call setForegroundState once the application returns to the front. This will make Websockets connect again and the logged user appear online again.

{% gist https://gist.github.com/warodri-sendbird/09534b05533e03763e08aa24e5cec70f file=Application state.js %}

[Gist](https://gist.github.com/warodri-sendbird/09534b05533e03763e08aa24e5cec70f)

After a successful connection, we store this user’s nickname (from the input screen) and return it to the Lobby component. Once the user is set, the **Channels** screen appears.

#Step 6. Building the Channels List component

![Channels list](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/84jogry71psko5jwp5n7.png)<center>*Channels list*</center><br>

Sendbird works with public **Open Channels** and **Group Channels**. You don’t need an invitation, any user can enter a message, for the **Open Channels**. **Group Channels** are the opposite. You need an invitation to join the channel and send messages.

To learn more about channel types, see [this page](https://sendbird.com/docs/chat/v3/javascript/guides/channel-types#1-channel-types) or [this tutorial](https://sendbird.com/developer/tutorials/understanding-channels).

Now, open the ./src/page/channels.js file and see all the essential parts that should be there.

* Add a connection handler to receive Websocket disconnections notifications. 

Customers must know when the SDK is not connected because your application should stop all requests until a connection is made. Otherwise, your users will think that your application is not working.

* Add a channel handler to receive updates from Sendbird about any events. You will be able to react to channel modifications, new messages, users being added or removed from channels, etc.

A channel handler helps your application to update visually and inform the customer about any changes made by other users. 

{% gist https://gist.github.com/warodri-sendbird/35b9d2fc74cd822d2bffef98d1c7b752 file= Channels - Add Handlers.js %}

[Gist](https://gist.github.com/warodri-sendbird/35b9d2fc74cd822d2bffef98d1c7b752)

Also, remember to remove your handlers when destroying each view.

{% gist https://gist.github.com/warodri-sendbird/34077cc248cf4e6d626f9bdf9d705702 file=Channels - Remove handlers.js %}

[Gist](https://gist.github.com/warodri-sendbird/34077cc248cf4e6d626f9bdf9d705702)

Read more about connection and channel handlers [here](https://sendbird.com/docs/chat/v3/javascript/guides/event-handler#1-event-handler). 

###Listing your channels

When listing channels, the maximum number of records you can receive from the server is 100. If you need more, you must use next(…) to call the server again:

{% gist https://gist.github.com/warodri-sendbird/127b561198d8b99a511e5a2d7290499d file=Channels - Executing next.js %}

[Gist](https://gist.github.com/warodri-sendbird/127b561198d8b99a511e5a2d7290499d)

Once the user selects a channel, our application will navigate to the chat, passing the selected channel and current signed user.

{% gist https://gist.github.com/warodri-sendbird/5019d9973dbb373aefb3aa34fc9cc526 file=Channels - Select channel.js %}

[Gist](https://gist.github.com/warodri-sendbird/5019d9973dbb373aefb3aa34fc9cc526)

This leads us to the messages screen.   

#Step 7. Building the Messages components

After selecting a channel, the application will show you a list of messages for this channel only:

![Messages](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f1c7u2i81ttb3q3m0kli.png)<center>*Messages*</center><br>

The code for this screen is in **./src/page/chat.js**.

Naturally, the list of messages is the most important part of this screen. But let’s take a look at other parts that must be included:

* A connection handler to manage disconnections and stop customers from sending messages.

* A channel handler to receive any changes related to the channels (including messages added, removed, etc.), via Websockets.

{% gist https://gist.github.com/warodri-sendbird/01b5a3eb6f334cb75b66bcb1a1b9f5ee file=Chat - Add handlers.js %}

[Gist](https://gist.github.com/warodri-sendbird/01b5a3eb6f334cb75b66bcb1a1b9f5ee)

You need to remove these handlers when this view is no longer active for users.

{% gist https://gist.github.com/warodri-sendbird/7bee990398d20803a15656ffd1466b7c file=Chat - Remove handlers.js %}

[Gist](https://gist.github.com/warodri-sendbird/7bee990398d20803a15656ffd1466b7c)

In this sample application, we will take action for the following events:

**onMessageReceived**: A new message is received via Websocket. Add this new message to the list of messages only if the channel URL informed from the event is the same channel you have active in this view.

**onMessageUpdated**: A message has been updated. If this informed message belongs to this active channel, you must update its content from the list.

**onMessageDeleted**: A message has been deleted. If this informed message belongs to this active channel, you must remove it from the list.

You can also receive events about to this user and the channel. For example:

**onUserLeft**: If a user left the channel, you should check if the signed user ID matches the informed user ID. If both are the same, it means that you decided to leave the channel from another device. Your action should be something like going back to the main list of channels (channels.js).

**onChannelDeleted**: Another critical check is the existence of the channel that contains the messages you are showing. If this channel is missing for any reason, you should also return to the main screen with the list of remaining channels (channels.js).

###Mark channel as read

When you enter to see the messages in a channel, you should mark all messages as read. 

{% gist https://gist.github.com/warodri-sendbird/b2f1150d50cb1017883873850d30a349 file=Chat - Mark channel as read.js %}

[Gist](https://gist.github.com/warodri-sendbird/b2f1150d50cb1017883873850d30a349)

###Listing your messages

We will ask Sendbird for the list of messages in this active channel. To do this, we use createPreviousMessageListQuery

{% gist https://gist.github.com/warodri-sendbird/b2f1150d50cb1017883873850d30a349 file=Chat - Mark channel as read.js %}

[Gist](https://gist.github.com/warodri-sendbird/b2f1150d50cb1017883873850d30a349)

To view more information, see [this page](https://sendbird.com/docs/chat/v3/javascript/guides/group-channel#2-load-previous-messages). You can also check out this [tutorial](https://sendbird.com/developer/tutorials/designing-message-objects) about messaging objects.

For this example, we list the last 50 messages. If more messages are available to show, you should call next() to get more data.

{% gist https://gist.github.com/warodri-sendbird/710552845828c264feca5468e37d57e1 file=Chat - Next messages.js %}

[Gist](https://gist.github.com/warodri-sendbird/710552845828c264feca5468e37d57e1)

###Getting messages according to the timestamp

You also can request a list of messages according to a specific timestamp. Use something like new Date().getTime() and define how many previous messages you want to show. 

This technique will help you load previous messages if the user scrolls up to get a long history of messages. You just need to keep sending the message’s timestamp and ask for previous records to show until you reach the first message sent to the channel.

{% gist https://gist.github.com/warodri-sendbird/4f204794dd661dbdaeed954e28223d0d file=get-message-by-timestamp.js %}

[Gist](https://gist.github.com/warodri-sendbird/4f204794dd661dbdaeed954e28223d0d)

To find more information, check our [docs](https://sendbird.com/docs/chat/v3/javascript/guides/group-channel#2-list-messages-along-with-their-replies-3-by-timestamp).

#Step 8. Sending and receiving messages

![Sending a message](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l1sp9ze6s91v80s1eiog.png)<center>*Sending a message*</center><br>

With Sendbird, you can send a text or a file message. 

Note that a message for Sendbird is not just a text or a file; we have other attributes to send confidential information to your server or to the other connected users. 

###Custom type

This attribute is part of the message object, and it specifies a custom message type for message grouping. The length is limited to 128 characters.

The Sendbird [Advanced Analytics](https://sendbird.com/docs/chat/v3/platform-api/guides/advanced-analytics) also uses Custom types to segment metrics. They enable the sub-classification of data views.

###Data

Data is another attribute you can use for your internal logic. It specifies additional message information such as custom font size, font type, or any data you want to handle with a JSON formatted string.

To find a list of attributes for a message, click [here](https://sendbird.com/docs/chat/v3/platform-api/guides/messages#4-list-of-properties-for-text-message).

To get more information about sending a message via the SDK and Javascript, see [this page](https://sendbird.com/docs/chat/v3/javascript/guides/group-channel#2-send-a-message).

Below is the code to send a message.  

{% gist https://gist.github.com/warodri-sendbird/47ac2cd2e81a0f508ffb492a477fdf84 file=Chat - Sending a message.js %}

###File messages

With Sendbird, you can also send file messages. In this application, we allow users to select the file from the device and then send it.

{% gist https://gist.github.com/warodri-sendbird/01c7073f281d7d3962ef637d077922ac file=Chat - Send file message.js %}

[Gist](https://gist.github.com/warodri-sendbird/01c7073f281d7d3962ef637d077922ac)

<span style="color:purple">***Remember to request permission.***</span>

When working with Android and iOS, you must request permission from users before using a file picker.

{% gist https://gist.github.com/warodri-sendbird/ca0d119667480ef0e6b2cf2258fcddd7 file=Chat - Send file message - Request permission.js %}

[Gist](https://gist.github.com/warodri-sendbird/ca0d119667480ef0e6b2cf2258fcddd7)

**Important**: Sendbird requires a Javascript **File** object as the file to upload. You may receive errors or have a failed upload if trying to send another format. Sometimes, the custom file pickers used from public repositories don’t deliver the proper object type.

Remember that when sending file messages, you cannot send text along with it. However, you can use other message object attributes to send a text and display it on the chat list. Check out the list of available attributes for a file message:

{% gist https://gist.github.com/warodri-sendbird/7ed1bc74c3e2ff5724ea8698b998bda4 file=send-file-message-raw-file.js %}

[Gist](https://gist.github.com/warodri-sendbird/7ed1bc74c3e2ff5724ea8698b998bda4)

More information is in the [docs](https://sendbird.com/docs/chat/v3/javascript/guides/group-channel#2-send-a-message).

###Thumbnails for image files

When uploading image files, you can ask Sendbird to generate a thumbnail automatically. Enable this from your [dashboard](https://dashboard.sendbird.com/auth/signin):

![A screenshot of enabling the auto thumbnail generator](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/86lcev65sopbq3chnwnk.png)<center>*Enable auto thumbnail generator*</center><br>

###Voice messages

You can send voice messages with file messages. Your frontend application should implement a voice recording function and save the result as a file. Then you just upload that file, along with any of the custom attributes we provide for the message object, indicating that this is a voice message file. When drawing this message in the channel, analyze the information and show it properly.

![Screenshot depicting a voice message](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2qxjtl11ywrsyww3ts2f.png)<center>Formatting a file message as a voice message</center><br>

###Reply to messages
Sendbird supports message threading so you can respond to messages. 

To do this, you must indicate the parent message ID when sending a response.

You can respond with a text message:

{% gist https://gist.github.com/warodri-sendbird/ae8804a26a9dd49a262a8b0b74cf8bde file=send-user-message.js %}

[Gist](https://gist.github.com/warodri-sendbird/ae8804a26a9dd49a262a8b0b74cf8bde)

Or with a file message:

{% gist https://gist.github.com/warodri-sendbird/6747e2828741e505a84f2975130b75c0 file=send-file-message.js %}

[Gist](https://gist.github.com/warodri-sendbird/6747e2828741e505a84f2975130b75c0)

To learn more about messages, check out the [docs](https://sendbird.com/docs/chat/v3/javascript/guides/group-channel#2-reply-to-a-message) and this [tutorial](https://sendbird.com/developer/tutorials/designing-message-objects).

#Step 9. Other Sendbird features

Sendbird offers a variety of features for your chat experience.

###Typing indicators

In this example, you can see the use of startTyping() and endTyping() to send events to all members in the channel.

{% gist https://gist.github.com/warodri-sendbird/a3071a18a82f594fdee524fbdd598dde file=Chat -Typing indicator.js %}

[Gist](https://gist.github.com/warodri-sendbird/a3071a18a82f594fdee524fbdd598dde)

This event triggers the onTypingStatusUpdated function from the [channel handler](https://sendbird.com/docs/chat/v3/javascript/guides/event-handler#4-list-of-open-channel-events).

The rest is to show a label saying that user XXX is typing a message.

###Moderation

Sendbird provides powerful tools for moderation. You can use the Sendbird [Dashboard](https://dashboard.sendbird.com/auth/signin) to moderate messages and users. You may also [register](https://sendbird.com/docs/chat/v3/javascript/guides/group-channel#2-register-operators) or [unregister](https://sendbird.com/docs/chat/v3/javascript/guides/group-channel#2-cancel-the-registration-of-operators) channel members as [Operators](https://sendbird.com/docs/chat/v3/javascript/guides/user-types#2-operator) so that they can [freeze](https://sendbird.com/docs/chat/v3/javascript/guides/group-channel#2-freeze-and-unfreeze-a-channel) channels, [block](https://sendbird.com/docs/chat/v3/javascript/guides/group-channel#2-ban-and-unban-a-user), or [mute](https://sendbird.com/docs/chat/v3/javascript/guides/group-channel#2-mute-and-unmute-a-user) users. 

To review all the features that Sendbird offers, check out our JavaScript [docs](https://sendbird.com/docs/chat/v3/javascript/quickstart/send-first-message) and this tutorial for [moderation best practices](https://sendbird.com/developer/tutorials/reporting-api-best-practice).

#Conclusion

So that’s a wrap! Many more features are available in the JavaScript SDK, so make sure to check out [the documentation](https://sendbird.gitbooks.io/sendbird-javascript-sdk/content/) to build an even more advanced messaging app.

This tutorial gave you a taste for building a React Native chat app with the [Sendbird JavaScript SDK](https://sendbird.com/docs/chat/v3/javascript/quickstart/send-first-message). To learn more about React Native, refer to the [official documentation](https://reactnative.dev/docs/getting-started.html).

If you have any questions regarding this tutorial or using Sendbird in general, please drop us a note on our [community page](https://community.sendbird.com/).

Thanks, and happy React Native chat building!