index.js
file, add the following lines:<mitter-api-url>
, use the following value:mitterApiBaseUrl
key in the config or explicitly set it to https://api.mitter.io
http://localhost:<port>
where the port is port forwarded by docker for 11902
. To find out which port it is, run the following command docker port $(docker ps --filter expose=11901-11903/tcp --format "")
<distributor-url>
, use the following value:weaverUrl
key in the config or explicitly set it to https://weaver.mitter.io
http://localhost:<port>
where the port is port forwarded by docker for 11903
. To find out which port it is, run the following command docker port $(docker ps --filter expose=11901-11903/tcp --format "")
mitter
object we created to the App
component so that it can fetch the user data and render it. At the end of this, your index.js
file should look something like:ChannelComponent
. We'll move it to the state for the App
component. Also, we'll pass on the Mitter object to the the ChannelComponent
as we will need to send messages later on.render()
function to now pass the channelMessages
prop from App
via a state rather than the hard-coded variable. If you reload your application, you'll see a blank page. In your App
component, we will now fetch a list of channels for the user. We will do this in the componentDidMount()
method:NOTE Do note that for a messaging-based application, the architecture of this application is not a recommended one. Ideally, you should be using a state management system likeredux
orflux
, but for the sake of simplicity we are not using this in the application so that we can focus on introducing Mitter.io concepts. There is also a packagemitter-redux
currently in alpha that builds atop redux and handles all intricacies of state management which should be used in production apps.
http://localhost:3000/user/@john
to http://localhost:3000/user/@candice
and you should now see only one channel (#roadtrip
) as opposed to two channels earlier.componentDidMount()
function (also pay attention to the additional import isNewMessagePayload
at the top of the file):newMessage
method should now look:prevState
. While you may not encounter this frequently, Mitter.io might occasionally send duplicate messages on a payload. This usually happens when Mitter.io cannot confidently determine that a message delivery has occurred, but it might still have propagated. Also, the current implementation performs an entire iteration of the messages in a channel, which might not be very efficient. As an exercise to the reader, modify this to a store backed by a hashing algorithm.concat
this message on to the list of messages for the given channel.NOTE There are certain caveats with this approach, notably that you might get receive payloads for messages for which you do not have a channels object yet. This could happen if a user was added to a channel after the participated channels were fetched. While such a situation will not arise in our setup, production apps need to always be resilient to partial state and must reconstruct the state in whatever form they can from the available events.
Send
button in our ChannelComponent
. We'll add a few methods, namely sendMessage()
and updateTypedMessage
to ChannelComponent
. Also, we'll set up the handlers on the input fields as we usually do for any React App. The input components will now look like this:updateTypedMessage
is your standard message to store the state of an input field, and have a way to control it. Let us look into what we are doing in the sendMessage
function. Pay attention to the numbered labels in the code:messageInput
field (this property is set in the ref callback of the <input>
field)senderId
, textPayload
have been discussed before, timelineEvents
are something new. Let's discuss them for a while.TimelineEvent
is used to record events that occur for a given entity. Mitter.io supports timeline events for Channels
and Messages
. For example, this is what is used to store and transmit read/delivered receipts. You are free to use any type of timeline events and interpret them as you wish, with the exception that they may not start with mitter.
or io.mitter.
. Also, any message that is sent must have a mitter.mtet.SentTime
timeline event attached to it. The server then attaches another timeline event recording the server receive time, synchronized to the servers clock.http://localhost:3000/user/@john
and http://localhost:3000/user/@candice
. Try exchanging a few messages between them and you'll notice that you have a working chat app!Send
and then let the network call take its time.