In this project i make the chat page with real-time update of messages over RTK Query and Socket Io.
Because of what backend deployed on the free tier services, you need wait a couple minutes to wake up docker container. Open DevTools to check is the request passing with 200.
Check chatApi.ts
on the Client to see implementation:
The first thing it connect to backend via socket io.
const socket = io(`https://chatback.fly.dev`, {
transportOptions: {
polling: {
extraHeaders: {
'Authorization': `Bearer ${token}`,
},
},
},
});
Then when the socket.emit
message is send via mutation traugh RTKQ from client,
sendMessage: builder.mutation({
query: ({ token, message }) => ({
url: 'messages',
method: 'POST',
body: message,
headers: {
'Content-type': 'application/json; charset=UTF-8',
'authorization': `Bearer ${token}`
},
}),
invalidatesTags: ['Messaages'],
async onQueryStarted(arg) {
socket.emit('sendAllMessages', arg.message)
}
})
it coming to the server and broadcasting this message to all other client:
const registerMessage = (client) => {
client.on('sendAllMessages', (arg) => {
client.broadcast.emit('getAllmessages', arg);
});
};
on the all clients first query to receive message, call async function that open websocket connection and wait for a new message:
allMessages: builder.query<Message[], string | null>({
query: (token) => ({
url: 'messages',
method: 'GET',
headers: {
'Content-type': 'application/json; charset=UTF-8',
'authorization': `Bearer ${token}`
},
}),
providesTags: ['Messaages'],
async onCacheEntryAdded(arg, { updateCachedData, cacheDataLoaded, cacheEntryRemoved }) {
try {
await cacheDataLoaded
const listener = (messages: Message) => {
updateCachedData((draft) => {
draft.push(messages)
})
}
socket.on('getAllmessages', listener)
} catch {
}
await cacheEntryRemoved
socket.close()
}
}),