Tutorial: How to Build a Slack Clone with React Native — Part 3
Tags: reactnative, slackclone, chat, getstream
Published: 2020-11-17 16:06:03

In [Part 2](https://getstream.io/blog/slack-clone-with-stream-chat-part-2/) of this tutorial, we covered how to build Slack-like navigation, channel list screen, channel screen, reaction picker, and action sheet. In this tutorial, Part 3, we will build various search screens and thread screen.

## Resources 👇

Below are a few helpful links if you get stuck along the way:

- [Official Slack Clone Repo](https://github.com/GetStream/slack-clone-react-native)
- [Official Slack Clone Repo for Expo](https://github.com/GetStream/slack-clone-expo)
- [Documentation for React Navigation](https://reactnavigation.org/)
- [Stream Chat Component Library](https://github.com/GetStream/stream-chat-react-native)

## Thread Screen

- The `MessageList` component accepts the prop function `onThreadSelect`, which is attached to the [onPress handler](https://github.com/GetStream/stream-chat-react-native/blob/master/src/components/Message/MessageSimple/MessageContent.tsx#L260) for reply count text below the message bubble. If you check our `ChannelScreen` component, you will see navigation logic to `ThreadScreen` added to the `onThreadSelect` prop on the `MesaageList` component.

- [`Thread`](https://github.com/GetStream/stream-chat-react-native/blob/master/src/components/Thread/Thread.tsx) is provided out-of-the-box from `stream-chat-react-native`. If you look at the source code, it's a set of `Message` (parent message bubble), `MessageList`, and a `MessageInput` component. You can customize these underlying components using props – `additionalParentMessageProps`, `additionalMessageListProps` and `additionalMessageInputProps`. We can use this Thread component easily for our purpose.

- We need to implement a checkbox labeled "Also send to {channel_name}" (as shown in the screenshot below). When ticked, the message should appear on the channel as well. We can use `show_in_channel` property on the message object for this, as mentioned in docs for [threads and replies](https://getstream.io/chat/docs/threads/?language=js)

> If you specify `show_in_channel`, the message will be visible both in a thread of replies and the main channel.

![Thread Reply in the Channel](https://stream-blog-v2.imgix.net/blog/wp-content/uploads/73910013f424a774f1154b9ca7692f08/Screenshot-2020-11-04-at-11-44-16.png)

If the checkbox is ticked, add `show_in_channel: true` to the message object before sending it. We can achieve this by providing a `doSendMessageRequest` prop function, which overrides Channel components default sendMessage handler.

![Input box for thread](https://stream-blog-v2.imgix.net/blog/wp-content/uploads/02cf0ddb76529ca4d9ef85ccf1c4aafb/inputboxthread.gif)

Use the [Animated API](https://reactnative.dev/docs/animated) by React Native to achieve the sliding animation of the checkbox and other action buttons.

{% gist https://gist.github.com/vishalnarkhede/f337314921224c57bcf0950482611bab %}

Now assign the `ThreadScreen` component to its respective `HomeStack.Screen` in `App.js`.

{% gist https://gist.github.com/nparsons08/cf3b6655fce9cd30fec0780835b6c130 %}

## Search Screens

There are four modal search screens that we are going to implement in this tutorial:

![Slack Clone Layout](https://stream-blog-v2.imgix.net/blog/wp-content/uploads/058210eff54bc0a461169548608987f6/Screenshot-2020-11-03-at-07-40-09.png)

### Jump to Channel Screen & Channel Search Screen

We can create a standard component for Jump to channel screen and Channel search screen.

Let's first create a common component needed across the search screens.

### Direct Messaging Avatar

This is a component for the avatar of direct messaging conversation:

- For one to one conversations, it shows other member's picture with his presence indicator
- For group conversation, it shows stacked avatars of two of its members.

![Status Indicators](https://stream-blog-v2.imgix.net/blog/wp-content/uploads/d1f56140939b3464f518f32be556a1a2/Medium-article-01.png)

{% gist https://gist.github.com/vishalnarkhede/3d245e68298da4886b60fb99b5a31b94 %}

### Modal Screen Header

This is a common header for modal screens, with a close button on the left and title in the center.

{% gist https://gist.github.com/vishalnarkhede/42bd301af6d780df9abda28b55a2d4f2 %}

Now let's build a `ChannelSearchScreen`, which can be used as "Jump to channel screen" and "Channel search." There are two main differences between these screens, which we will control through a prop — `channelsOnly`.

1. "Jump to channel screen" doesn't have a header
2. "Channel search screen" doesn't have a horizontal list of recent direct messaging conversation members.

Also, we need to display a list of recent conversations when the user opens this modal. We can use the cached list of recent conversations in `CacheService` (which we populated in the `ChannelList` component via the `useWatchedChannels` hook) to avoid extra calls to the `queryChannels` API endpoint.

{% gist https://gist.github.com/vishalnarkhede/8e552bc2224e9c0da675c65ed290c967 %}

Assign the `ChannelSearchScreen` component to its respective `ModalStack.Screen` in `App.js`.

{% gist https://gist.github.com/nparsons08/b9bc7153e9db2c799920b9543dbb37fc %}

## New Message Screen

Highlights of this screen (`NewMessageScreen`) are as following:

1. Inputbox on top is a multi-select input. One can select multiple users there. This can be quickly built as a separate component — `UserSearch`. Expose `onChangeTags` callback as a prop function to give parent component access to selected users.
2. `UserSearch` component uses `queryUsers` endpoint provided available on chat client. Please check [docs for `queryUser` endpoint](https://getstream.io/chat/docs/query_users/?language=js&q=queryUser)
3. When the user focuses on the input box at the bottom of the screen, the app should create a conversation between the already selected users in the top (`UserSearch`) input box. We handle this in the `onFocus` handler for the input box at the bottom of the screen.

{% gist https://gist.github.com/vishalnarkhede/8ae134519183bdae6c43234cac1c7910 %}

Now assign the `NewMessageScreen` component to its respective `ModalStack.Screen` in `App.js`.

{% gist https://gist.github.com/nparsons08/c03d627c760a7b45e3bb4015ec43ff0e %}

### Message Search Screen

We are going to implement a global search for message text on this screen — `MessageSearchScreen`.

> **Note**: The official Slack app provides richer features such as search in a specific channel or search by attachments. Here, we are keeping it limited to a global search, although channel-specific search is also possible using [Stream Search API](https://getstream.io/chat/docs/search/?language=js)

1. Global message search is relatively heavy for the backend so that search won't happen onChangeText, but when the user presses the search button explicitly. TextInput component has [`returnKeyType`](https://reactnative.dev/docs/textinput#returnkeytype) prop which we need for our use case.
2. Component uses `search` endpoint available on chat clients. Please check [docs for message endpoint](https://getstream.io/chat/docs/search/?language=js)
3. Search results display a list of messages; when pressed, they should go to the channel screen on that particular message. We are going to build a separate screen for this — `TargettedMessageChannelScreen`. This component is quite similar to `ChannelScreen`, but it queries the channel at a specific message (provided through props) instead of the latest message as follows:

{% gist https://gist.github.com/nparsons08/4517ac6f5d9ce88581dc2546af37f81a %}

4. When the user lands on this screen, he can see the list of past searches. Store every search text in AsyncStorage.

Copy the following components in your app:

{% gist https://gist.github.com/vishalnarkhede/55c4955c00c1110511f51fd7b514e286 %}

Assign the `MessageSearchScreen` and `TargettedMessageChannelScreen` component to its respective `ModalStack.Screen` in `App.js`.

{% gist https://gist.github.com/nparsons08/6b93999f6320ab85c60407ad5aedf100 %}

Implementation for additional more screens (shown in screenshots below) is available in [slack-clone-react-native](https://github.com/GetStream/slack-clone-react-native/) repository. If you managed to follow the tutorial so far, implementation of following screens should be easy to understand.

- [Direct Messages screen](https://github.com/GetStream/slack-clone-react-native/tree/master/src/screens/DirectMessagesScreen.js)
- [Mentions screen](https://github.com/GetStream/slack-clone-react-native/tree/master/src/screens/MentionsSearch.js)
- [Draft Messages screen](https://github.com/GetStream/slack-clone-react-native/tree/master/src/screens/DraftsScreen.js)

## Congratulations! 👏

![Chat Slack Clone](https://stream-blog-v2.imgix.net/blog/wp-content/uploads/b5c1176ca5f8c9d43dae34d3bc5d6c5d/combine-images.png)

You've completed Part 3, the final step, of our tutorial on building a Slack clone using the [Stream’s Chat](https://getstream.io/chat/) API with [React Native](https://www.npmjs.com/package/stream-chat-react-native). I hope you found this tutorial helpful!

Happy coding!