Skip to content

Channel markReadOnMount does not work if the channel was not initialized before #3067

Open
@danmana

Description

@danmana

When opening a <Channel> directly, with an uninitialized channel the auto markRead functionality does not work.
Note that we are not coming from the ChannelList, but from one of our components directly opening a <Channel>.

Something like this

const channel  = client.channel('messaging', channelId);

  return (
    <Channel channel={channel}>
      <MessageList />
      <MessageInput />
    </Channel>
  );
  1. In the initChannel useEffect, the unreadCount is not correct when read at the top, because the channel was not yet watched/initialized (which happens a few lines below)

const initChannel = async () => {
setLastRead(new Date());
const unreadCount = channel.countUnread();
if (!channel || !shouldSyncChannel || channel.offlineMode) {
return;
}
let errored = false;
if (!channel.initialized || !channel.state.isUpToDate) {
try {
await channel?.watch();
} catch (err) {
console.warn('Channel watch request failed with error:', err);
setError(true);
errored = true;
}
}

Moving the const unreadCount = channel.countUnread(); after the .watch() solves this.

  1. In initChannel when markRead is called (for a freshly initialized channel), the clientChannelConfig closure is still undefined, and markRead will do nothing.

clientChannelConfig will become defined only on the next render, but getChannelConfigSafely() is defined because we just called .watch()

if (unreadCount > 0 && markReadOnMount) {
await markRead({ updateChannelUnreadState: false });
}

const markRead: ChannelContextValue<StreamChatGenerics>['markRead'] = throttle(
async (options?: MarkReadFunctionOptions) => {
const { updateChannelUnreadState = true } = options ?? {};
if (!channel || channel?.disconnected || !clientChannelConfig?.read_events) {
return;
}

Changing clientChannelConfig to getChannelConfigSafely() fixes the issue


Here is a patch I generated for stream-chat-react-native-core@6.7.1 using patch-package, which fixes the markRead issues on an un-initialized channel

diff --git a/node_modules/stream-chat-react-native-core/src/components/Channel/Channel.tsx b/node_modules/stream-chat-react-native-core/src/components/Channel/Channel.tsx
index 1bc8ad5..fe31bd0 100644
--- a/node_modules/stream-chat-react-native-core/src/components/Channel/Channel.tsx
+++ b/node_modules/stream-chat-react-native-core/src/components/Channel/Channel.tsx
@@ -826,7 +826,6 @@ const ChannelWithContext = <
     let listener: ReturnType<typeof channel.on>;
     const initChannel = async () => {
       setLastRead(new Date());
-      const unreadCount = channel.countUnread();
       if (!channel || !shouldSyncChannel || channel.offlineMode) {
         return;
       }
@@ -842,6 +841,9 @@ const ChannelWithContext = <
         }
       }
 
+      // Fix: count unread messages after channel is initialized/watched
+      const unreadCount = channel.countUnread();
+
       if (!errored) {
         initStateFromChannel(channel);
         loadInitialMessagesStateFromChannel(channel, channel.state.messagePagination.hasPrev);
@@ -947,7 +949,8 @@ const ChannelWithContext = <
   const markRead: ChannelContextValue<StreamChatGenerics>['markRead'] = throttle(
     async (options?: MarkReadFunctionOptions) => {
       const { updateChannelUnreadState = true } = options ?? {};
-      if (!channel || channel?.disconnected || !clientChannelConfig?.read_events) {
+      // Fix: use getChannelConfigSafely() instead of clientChannelConfig because of closure issue when the channel is initialized in initChannel
+      if (!channel || channel?.disconnected || !getChannelConfigSafely()?.read_events) {
         return;
       }
 

This issue body was partially generated by patch-package.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions