stream-chat-react
stream-chat-react copied to clipboard
feat: update thread messages in the background based on WS events
Motivation Every time the Thread component is rendered a new HTTP request is fired to retrieve its data. This happens even though the client could update the thread state based on incoming WS events:
New thread reply event (`message.new` with the `parent_id` attr)
{
"type": "message.new",
"cid": "messaging:brazil",
"channel_id": "brazil",
"channel_type": "messaging",
"message": {
"id": "SmithAnne-RagV8FZgHpmPMb2ES8wda",
"text": "b",
"html": "<p>b</p>\n",
"type": "reply",
"user": {
"id": "SmithAnne",
"role": "user",
"created_at": "2022-01-27T08:28:28.412254Z",
"updated_at": "2022-05-05T19:19:25.913957Z",
"last_active": "2022-06-09T09:14:23.653692038Z",
"banned": false,
"online": true,
"image": "https://cdn.fakercloud.com/avatars/miguelkooreman_128.jpg",
"nickname": "Ann",
"name": "SmithAnne"
},
"attachments": [],
"latest_reactions": [],
"own_reactions": [],
"reaction_counts": {},
"reaction_scores": {},
"parent_id": "SmithAnne-Vmzj4d94czPfMdSg4aeXN",
"reply_count": 0,
"cid": "messaging:brazil",
"created_at": "2022-06-09T09:22:19.552958Z",
"updated_at": "2022-06-09T09:22:19.552958Z",
"shadowed": false,
"mentioned_users": [],
"silent": false,
"pinned": false,
"pinned_at": null,
"pinned_by": null,
"pin_expires": null
},
"user": {
"id": "SmithAnne",
"role": "user",
"created_at": "2022-01-27T08:28:28.412254Z",
"updated_at": "2022-05-05T19:19:25.913957Z",
"last_active": "2022-06-09T09:14:23.653692038Z",
"banned": false,
"online": true,
"nickname": "Ann",
"name": "SmithAnne",
"image": "https://cdn.fakercloud.com/avatars/miguelkooreman_128.jpg"
},
"watcher_count": 1,
"created_at": "2022-06-09T09:22:19.567940859Z"
}
Parent message update event
{
"type": "message.updated",
"cid": "messaging:brazil",
"channel_id": "brazil",
"channel_type": "messaging",
"message": {
"id": "SmithAnne-Vmzj4d94czPfMdSg4aeXN",
"text": "",
"html": "",
"type": "regular",
"user": {
"id": "SmithAnne",
"role": "user",
"created_at": "2022-01-27T08:28:28.412254Z",
"updated_at": "2022-05-05T19:19:25.913957Z",
"last_active": "2022-06-09T09:14:23.653692038Z",
"banned": false,
"online": true,
"nickname": "Ann",
"name": "SmithAnne",
"image": "https://cdn.fakercloud.com/avatars/miguelkooreman_128.jpg"
},
"attachments": [
{
"type": "audio",
"title": "Audio Clip (2022-03-21_10-23-53-413).m4a",
"asset_url": "https://us-east.stream-io-cdn.com/1145265/attachments/e1d6a888-f6b9-4a5a-b3f0-ac99049712fb.Audio%20Clip%20%282022-03-21_10-23-53-413%29.m4a?Key-Pair-Id=APKAIHG36VEWPDULE23Q&Policy=eyJTdGF0ZW1lbnQiOlt7IlJlc291cmNlIjoiaHR0cHM6Ly91cy1lYXN0LnN0cmVhbS1pby1jZG4uY29tLzExNDUyNjUvYXR0YWNobWVudHMvZTFkNmE4ODgtZjZiOS00YTVhLWIzZjAtYWM5OTA0OTcxMmZiLkF1ZGlvJTIwQ2xpcCUyMCUyODIwMjItMDMtMjFfMTAtMjMtNTMtNDEzJTI5Lm00YSoiLCJDb25kaXRpb24iOnsiRGF0ZUxlc3NUaGFuIjp7IkFXUzpFcG9jaFRpbWUiOjE2NTU5NzM0NjJ9fX1dfQ__&Signature=k~QKGZLR~z6zC~1-F~NPPOaYOcbWbyK4tqhozWAMujDYdwe1D2IfVXhLoqGlz9TmvGTVek96TrNAdr70LbqDBn7LRByRYZIkOW7iNvqmi0kTjmboEaiMhhd8muFy2vlPImZLNv7ecv-56~Xj0HW5NzCC3qFHUu-k-XquUxKUxife1CJgT2JvuljaOzt0BcMoUJGoM8DAYsavq9wx~ZF1xXNzVFsmLR6-eFgAV4pqIk85dWpS-aak~E4Mcvtv5rM7IqfQ0G-ty2oAqFqx14-E6u4YZUgpQw9BrMKudzS9BBbV-r6Vk2rRMK-cUV6Wg6eNtaVmuUk6cHZJee4osrfqzA__",
"file_size": 36132,
"mime_type": "audio/x-m4a"
}
],
"latest_reactions": [],
"own_reactions": [],
"reaction_counts": {},
"reaction_scores": {},
"reply_count": 2,
"thread_participants": [
{
"id": "SmithAnne",
"role": "user",
"created_at": "2022-01-27T08:28:28.412254Z",
"updated_at": "2022-05-05T19:19:25.913957Z",
"last_active": "2022-06-09T09:14:23.653692038Z",
"banned": false,
"online": true,
"nickname": "Ann",
"name": "SmithAnne",
"image": "https://cdn.fakercloud.com/avatars/miguelkooreman_128.jpg"
}
],
"cid": "messaging:brazil",
"created_at": "2022-06-09T08:37:42.844888Z",
"updated_at": "2022-06-09T08:37:42.844888Z",
"shadowed": false,
"mentioned_users": [],
"silent": false,
"pinned": false,
"pinned_at": null,
"pinned_by": null,
"pin_expires": null
},
"user": {
"id": "SmithAnne",
"role": "user",
"created_at": "2022-01-27T08:28:28.412254Z",
"updated_at": "2022-05-05T19:19:25.913957Z",
"last_active": "2022-06-09T09:14:23.653692038Z",
"banned": false,
"online": true,
"name": "SmithAnne",
"image": "https://cdn.fakercloud.com/avatars/miguelkooreman_128.jpg",
"nickname": "Ann"
},
"created_at": "2022-06-09T09:22:19.567937971Z"
}
That way the loading UI could be shown only the first time the Thread component is open. Since then the client holds its reference in a mapping, which can be updated in the background as the WS events come in.
Acceptance Criteria
- Fire the
/repliesHTTP query only on the first opening of the existing thread (message loaded withreply_count> 0) - Display the UI loading indicator only when hitting the
repliesendpoint