Setup Confused about something? Let us know how we can improve: Submit

The easiest way to build a chat application with this tutorial is to create a new project using the `create-react-app` (CRA). CRA provides a boilerplate React application with all of the necessary configurations for modern JavaScript:

yarn global add create-react-app

Note: Make sure that you have the most recent version of Node.js and Yarn installed.

If you’re on macOS with Homebrew installed and don’t already have the requirements on your machine, you can run the following command:

brew install node && brew install yarn

Next, run the following commands to create a new React project called `chat-example`.

create-react-app chat-example cd chat-example yarn add stream-chat stream-chat-react

This will create the skeleton of the chat application project and install the Stream Chat Components.

The first part of this tutorial shows you how to build a WhatsApp / Facebook Messenger style chat and the second part of this tutorial shows how to build chat for a livestream event.

To follow the rest of this tutorial, you will need to get a free 4 weeks trial of Chat. No credit card is required.

Sign Up for Free Or proceed with a sandbox environment.

Part 1 - WhatsApp / Facebook Messenger Style Chat with React Confused about something? Let us know how we can improve: Submit

Message List & MessageInput

The core of the Chat interface from Stream is the message list component. Let's initialize the connection to Stream and configure the component. Replace the code in src/App.js with:

import React from 'react'; import { Chat, Channel, ChannelHeader, Thread, Window } from 'stream-chat-react'; import { MessageList, MessageInput } from 'stream-chat-react'; import { StreamChat } from 'stream-chat'; import 'stream-chat-react/dist/css/index.css'; const chatClient = new StreamChat('gx5a64bj4ptz'); const userToken = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiaG9seS1hcnQtNCJ9.sWEfUC5mgEOG6Tq2XUvGEe4SKzWhz_HJuE6umkWJI3Y'; chatClient.setUser( { id: 'holy-art-4', name: 'Holy art', image: 'https://getstream.io/random_png/?id=holy-art-4&name=Holy+art' }, userToken, ); const channel = chatClient.channel('messaging', 'godevs', { // add as many custom fields as you'd like image: 'https://cdn.chrisshort.net/testing-certificate-chains-in-go/GOPHER_MIC_DROP.png', name: 'Talk about Go', }); const App = () => ( <Chat client={chatClient} theme={'messaging light'}> <Channel channel={channel}> <Window> <ChannelHeader /> <MessageList /> <MessageInput /> </Window> <Thread /> </Channel> </Chat> ); export default App;

Next run yarn start to see the chat in action

Note how we're creating the `channel('messaging', 'godevs')` channel.

The first argument is the chat type and the second argument the chat ID

The chat type controls which features are enabled and the permissions associated with this chat

The chat ID is a unique reference to this specific channel

If you look at the following lines of code:

<Chat client={chatClient}> <Channel channel={channel} theme={'messaging light'}> <ChannelHeader /> <Window> <MessageList /> <MessageInput /> </Window> <Thread /> </Channel> </Chat>

These react chat components create a fully functional chat UI that is fully customizable. Out of the box you’ll notice that the following features are enabled:

URL unfurling/preview (Try sending a link to a Youtube video to see this in action)

Video Playback

File uploads & Previews

/slash commands such as /giphy and /imgur. You can also implement your own slash commands to make your chat environment and team more productive.

Presence – Who is online

Typing Indicators

Message Status Indicators (sending, received)

Automatic AI Powered Spam & Profanity Protection

Moderators & User Roles

Emoticons

Seen/Read Indicators

Threads & Replies

Reactions

Autocomplete on users, emoticons and commands

Channel List

The next example shows you how to render a list of channels. This component is convenient if you want to show a user a list of all the channels they are a member of.

The example below shows how to use the ChannelList component. Update src/App.js with the following code:

import React from 'react'; import { Chat, Channel, ChannelList, Window } from 'stream-chat-react'; import { ChannelHeader, MessageList } from 'stream-chat-react'; import { MessageInput, Thread } from 'stream-chat-react'; import { StreamChat } from 'stream-chat'; import 'stream-chat-react/dist/css/index.css'; const chatClient = new StreamChat('gx5a64bj4ptz'); const userToken = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiaG9seS1hcnQtNCJ9.sWEfUC5mgEOG6Tq2XUvGEe4SKzWhz_HJuE6umkWJI3Y'; chatClient.setUser( { id: 'holy-art-4', name: 'Holy art', image: 'https://getstream.io/random_png/?id=holy-art-4&name=Holy+art' }, userToken, ); const filters = { type: 'messaging', members: { $in: ['holy-art-4'] } }; const sort = { last_message_at: -1 }; const channels = chatClient.queryChannels(filters, sort); const App = () => ( <Chat client={chatClient} theme={'messaging light'}> <ChannelList filters={filters} sort={sort} /> <Channel> <Window> <ChannelHeader /> <MessageList /> <MessageInput /> </Window> <Thread /> </Channel> </Chat> ); export default App;

Note that ChannelList will automatically set the channel property of the Channel component.

Customizing your first component

The underlying API as well as the React Components are extremely flexible. With little to no coding, you can easily build any type of chat. The example below shows you how to swap out the default message component with your own. Update src/App.js with the following code:

import React from 'react'; import { Chat, Channel, ChannelList, Window } from 'stream-chat-react'; import { ChannelHeader, MessageList } from 'stream-chat-react'; import { MessageInput, Thread } from 'stream-chat-react'; import { StreamChat } from 'stream-chat'; import 'stream-chat-react/dist/css/index.css'; const chatClient = new StreamChat('gx5a64bj4ptz'); const userToken = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiaG9seS1hcnQtNCJ9.sWEfUC5mgEOG6Tq2XUvGEe4SKzWhz_HJuE6umkWJI3Y'; // custom channel preview component class MyChannelPreview extends React.Component { render() { const {setActiveChannel, channel} = this.props; const unreadCount = channel.countUnread(); return ( <div className="channel_preview"> <a href="#" onClick={(e) => setActiveChannel(channel, e)}> {channel.data.name} </a> <span> Unread messages: {unreadCount} </span> </div> ); } } // a very minimalistic message component class MyMessageComponent extends React.Component { render() { return <div><b>{this.props.message.user.name}</b> {this.props.message.text}</div>; } } chatClient.setUser( { id: 'holy-art-4', name: 'Holy art', image: 'https://getstream.io/random_png/?id=holy-art-4&name=Holy+art' }, userToken, ); const filters = { type: 'messaging', members: { $in: ['holy-art-4'] } }; const sort = { last_message_at: -1 }; const channels = chatClient.queryChannels(filters, sort); const App = () => ( <Chat client={chatClient} theme={'messaging light'}> <ChannelList filters={filters} sort={sort} Preview={MyChannelPreview} /> <Channel Message={MyMessageComponent}> <Window> <ChannelHeader /> <MessageList /> <MessageInput /> </Window> <Thread /> </Channel> </Chat> ); export default App;

The docs for the React Components are available here. If you are looking to build a more complex integration with Stream Chat, please look at our API docs here or try one of our other React tutorials.

Part 2: Live Stream Chat Example with React Confused about something? Let us know how we can improve: Submit

As a next exercise let's see how we can customize the above example to work well for a livestream.

Live Stream Chat

There are a few differences when building chat for a livestream:

The user interface is typically more compact

Typing as well as message seen/read states tend to get noisy

Have a look at the example below for building a livestream chat:

import React from 'react'; import { Chat, Channel, ChannelHeader, Window } from 'stream-chat-react'; import { MessageList, MessageInput, MessageLivestream } from 'stream-chat-react'; import { MessageInputSmall, Thread } from 'stream-chat-react'; import { StreamChat } from 'stream-chat'; import 'stream-chat-react/dist/css/index.css'; const chatClient = new StreamChat('gx5a64bj4ptz'); const userToken = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiaG9seS1hcnQtNCJ9.sWEfUC5mgEOG6Tq2XUvGEe4SKzWhz_HJuE6umkWJI3Y'; chatClient.setUser( { id: 'holy-art-4', name: 'Holy art', image: 'https://getstream.io/random_png/?id=holy-art-4&name=Holy+art' }, userToken, ); const channel = chatClient.channel('livestream', 'spacex', { image: 'https://goo.gl/Zefkbx', name: 'SpaceX launch discussion', }); const App = () => ( <Chat client={chatClient} theme={'livestream dark'}> <Channel channel={channel} Message={MessageLivestream}> <Window hideOnThread> <ChannelHeader live /> <MessageList /> <MessageInput Input={MessageInputSmall} focus /> </Window> <Thread fullWidth /> </Channel> </Chat> ); export default App;

There are a few important differences compared to the first example:

The theme is set to ‘livestream dark’ and is optimized for the compact layout next to a livestream.

We're using the livestream chat type. This chat type disables typing and seen/read states.

chat type. This chat type disables typing and seen/read states. The MessageInputSmall takes up less space. You can still use :emoticons: and other rich text input features.

Custom Message and Attachment Types

The Chat API allows you to store custom data for users, messages, events, channels and attachments, allowing for a fully customized chat experience. Build chat exactly how you want.

As an example, let’s say that you want to attach a product to your message. We'll do this by supporting a custom product message attachment:

import React from 'react'; import { Chat, Channel, Attachment } from 'stream-chat-react'; import { ChannelHeader, MessageList, Window } from 'stream-chat-react'; import { MessageInput, Thread } from 'stream-chat-react'; import { StreamChat } from 'stream-chat'; import 'stream-chat-react/dist/css/index.css'; const chatClient = new StreamChat('gx5a64bj4ptz'); const userToken = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiaG9seS1hcnQtNCJ9.sWEfUC5mgEOG6Tq2XUvGEe4SKzWhz_HJuE6umkWJI3Y'; class MyAttachmentComponent extends React.Component { render() { const {attachment} = this.props; if (attachment.type === 'product') { return ( <div className="product"> Product: <a href={attachment.url} target="_blank"> <img src={attachment.image} height={'100px'} /><br /> {attachment.name} </a> </div> ); } else { return <div>testing<Attachment {...this.props} /></div> } } } chatClient.setUser( { id: 'holy-art-4', name: 'Holy art', image: 'https://getstream.io/random_png/?id=holy-art-4&name=Holy+art' }, userToken, ); const channel = chatClient.channel('messaging', 'godevs', { // add as many custom fields as you like image: 'https://cdn.chrisshort.net/testing-certificate-chains-in-go/GOPHER_MIC_DROP.png', name: 'Talk about Go', }); const attachments = [{ type: 'product', name: 'iPhone', url: 'https://goo.gl/ppFmcR', image: 'https://goo.gl/J2gQpi', }] channel.sendMessage({ text: 'Your selected product is out of stock, would you like to select one of these alternatives?', attachments: attachments, }); const App = () => ( <Chat client={chatClient} theme={'messaging'}> <Channel channel={channel} Attachment={MyAttachmentComponent}> <Window> <ChannelHeader /> <MessageList /> <MessageInput /> </Window> <Thread /> </Channel> </Chat> ) export default App;

You could use a similar approach to embed any object from your site. Perhaps a livescore of a game, payments, location sharing or anything else you want to implement.

Final Thoughts Confused about something? Let us know how we can improve: Submit

We hope that you enjoyed this tutorial. By using Stream’s Chat Components, you and your team will be able to get your application, with chat, up and running in minutes.

Now that you’ve completed the tutorial on Stream Chat, you can build anything chat related with our components. If you need to build for other platforms, check out our react native chat or the iOS Swift Chat. If you have a use-case that doesn’t quite seem to work, or simply have questions, please don’t hesitate to reach out here.