Setting Up Your App
Setting up the project
In this tutorial, we will start with creating a basic chat application where users can chat with each other and then incrementally add more functionality to the app. For this app, we will be using React and generating the project using create-react-app
. However, to use the Mitter.io SDKs, you do not need to use React or even the create-react-app
utility. You can use any UI framework of your choice, and you can change the UI components accordingly.
You can also simply clone the mitter-web-starter
project from GitHub, which has all of this already setup for you.
Firstly, get the create-react-app
utility using npm
or yarn
Or using npm
Then create your app and install the dependencies
Now, you can start the app
This will open up the application in your default browser and you will see the standard React application with the placeholder content.
Let us first strip out all the placeholder stuff and just add a generic message. To do so, simply edit App.js
to look something like this:
Setting up users
In this example application, we will be adding three users with the usernames @john
, @amy
, @candice
. Among themselves, they will have two channels: #john-amy
which will be a direct channel be between @john
and @amy
, and a channel #vacation
which will be a channel between @john
, @amy
and @candice
. To recognize which user is which, we will use a pattern from the URL. So, when a user visits http://localhost:3000/user/@john
, it will recognize the user as @john
. To do so, open up index.js
and add the following code after the import statements:
Also, we need to pass this property to the App
component. Further down in the same file, pass this as a prop to App
Any call that is made to Mitter.io requires the caller to identify itself as an authenticated entity. There are a few anonymous calls that are allowed, but they offer little to no functionality and are present to facilitate the fetching of authorization for the user. In a real world scenario, you would get the user authorization from your application backend which acts as a source of truth. There is no way to anonymously fetch user authorization or to create a new user, unless the application has enabled federated authentication (in which case, the user still has to identify themselves via an authentication provider like Google OAuth).
One way to get user authorization tokens for development purposes (and development purposes ONLY) is to use the Mitter.io Dashboard to get user authorization tokens.
In the same Dashboard, we are going to create our users as well for the purposes of setting up this app. Do note that in a production environment, user management should also be done from a trusted source like an application backend.
Go to the Mitter.io Dashboard and navigate to the application that you created. In this application, navigate to the Users Panel and create three new users, setting their screen names to @john
, @amy
and @candice
. Do note that this is not the same as the user ID itself. When you create a user on Mitter.io, it generates a user ID automatically. Once you've done that, you can generate user tokens for each of these users. The token itself encodes the generated user ID for the user. You can inspect the contents of the token by decoding it, or online at https://jwt.io.
Put these user tokens in your index.js
file, mapping it to their user IDs:
We'll be using this information shortly. Meanwhile, let us build the basic UI for our application.
Creating a basic Chat UI
Let us add a few basic elements to this application, generic for any app
And the associated styling for this component to be added in App.css
(feel free to remove any content that is already there)
At this point, your app will look something like this
NOTE If you are using the
mitter-react-starter
project as your base, then this is the state you will start at.
So far it doesn't do much, and we need to add something that makes it more of a chat application. To do so, we will create two panels - one with a list of channels a user is a part of, and another panel that shows the messages in a selected channel. Here, we will introduce a component of an activeChannel
which is simply the channel that the user has currently selected.
Create two new files, ChannelComponent.js
and Channel.css
This is a pretty standard React component, but let's walk through the shapes of the component's state
and props
. In the constructor
you can see the state shape:
What we are doing is storing the currently active channel in the state, and a null
basically signifies that there is no channel currently selected. What we will be storing here is simply the identifier of the channel that is currently selected.
The props that it expects are of the shape:
We are storing all the messages in a channel in an array and are associating it in a dictionary with the channelId
as the key of the map. Once you have this, we need to render this component. Also we would really like to test out how this looks, so let us first create a mock of the data we expect:
Take a look at the channelMessages
object we created at the beginning of the file. This contains a list of messages in a map, mapped by the channel ID. Do note that all of this is simply dummy data which we will later wire to actual data from Mitter.io. The shape of the message object is what the Mitter.io platform uses in all of its request/response objects. The ones that are shown here are:
messageId
A globally unique ID for the message. Do note that this ID is namespaced by your application, not by the channel it is in, and hence is unique across all messages in your application.textPayload
A text representation of your message. Any message, be it a file, image, multimedia is always accompanied by a text representation of it. In this example app, we will be using this to render our messages.senderId
The identifier of the user who sent this message.
NOTE Mitter.io always sends out identifiers in an encapsulated object. Some IDs are also sent with specific names in top-level objects. For example, here
messageId
is directly a string, butsenderId
is an encapsulated object of the shape{identifier: '...'}
. The actual message object received from the server will have bothmessageId
and anidentifier
object as well, both pointing to the same ID. Refer to the docs on Mitter API modelling for more information.
Coming back to our ChannelComponent.js
file, take a look at the componentDidMount()
function:
Nothing fancy, but all that we are doing is setting the first channel as active if there are any channels that were passed to this object. And the render function for the same:
We iterate through the channel objects, and simply add a div for each channel that the user is a part of. We also add another class called active
to the tile of the channel that is currently active. The exact styles are as shown in Channel.css
a little above in the documentation.
Clicking on a channel tile sets that tiles channel to be the active channel, as can be seen in the function setActiveChannel
.
For rendering our messages, we are currently just stacking it over one another in the renderMessages()
function:
This doesn't look all that good, but we will get to styling it in a bit. So far, the application should look something like this:
What we would like to now do is align the messages that were sent by the logged in user to the right, and other messages to the left. We would also like to show the sender ID for messages not sent by us. To do so, we have to modify the renderMessages
function a bit:
What we are doing here is rendering the senderId
in the message block and we have also added some hierarchy to the overall message structure that will allow us to align it. Also, for messages sent by the current user (as checked on line no. 12, in the variable isSelfMessage
) we will attach another class self
to the top-level message element.
Add these following style definitions to the Channel.css
fileChannel.css
With this done, your app should now look something like:
Great going so far! Now what we need to do is wire up our application to consume the actual data from Mitter.io. To do this, let's head on over to the next section.
Last updated