SendbirdProvider onReconnectSuceeded GroupChannelHandler our

[Problem/Question]
There seems to be an issue with React-UI-kit implementation of SendbirdProvider and the Event handlers, that the sdk exposes.

Our application has some custom logic, so we fetch the channels from our own backend after ininitializing the React: application. (Backend is using the Platform API sdk). After fetching the channels we use the Event handlers that the UI-kit exposes like this:

 const globalStore = useSendbirdStateContext();
  const sdk = sendbirdSelectors.getSdk(globalStore);

// UTILS

  const getUnreadMessageCount = useCallback(
    async (customTypes: Array<ChannelCustomTypes>) => {
      if (typeof sdk === 'undefined' || sdk === null || Object.entries(sdk).length === 0) {
        return;
      }
      try {
        const messageCount = await sdk.groupChannel.getTotalUnreadMessageCount({
          channelCustomTypesFilter: customTypes,
        });
        return messageCount;
      } catch (error) {
        console.error('SendbirdError: ', error);
        return 0;
      }
    },
    [sdk],
  );

  const getUnreadMentionsCount = useCallback(async () => {
    if (typeof sdk === 'undefined' || sdk === null || Object.entries(sdk).length === 0) {
      return;
    }
    const params: UnreadItemCountParams = {
      keys: [
        UnreadItemKey.SUPER_UNREAD_MENTION_COUNT,
        UnreadItemKey.GROUP_CHANNEL_UNREAD_MENTION_COUNT,
        UnreadItemKey.GROUP_CHANNEL_UNREAD_MESSAGE_COUNT,
      ],
    };
    try {
      const unreadMentionsCount: UnreadItemCount | undefined = await sdk.groupChannel.getUnreadItemCount(params);
      if (unreadMentionsCount) {
        return (
          Number(unreadMentionsCount?.groupChannelUnreadMentionCount) +
          Number(unreadMentionsCount?.superGroupChannelUnreadMentionCount)
        );
      }
    } catch (error) {
      console.error('SendbirdError: ', error);
      return 0;
    }
  }, [sdk]);

  const updateUnreadTabs = useCallback(async () => {
    const courierUnreadCount = (await getUnreadMessageCount([ChannelCustomTypes.Couriers])) || 0;
    const jobUnreadCount = (await getUnreadMessageCount([ChannelCustomTypes.JobChat])) || 0;
    const activityUnreadCount = (await getUnreadMentionsCount()) || 0;
    dispatch(setUnreadMessagesCount(courierUnreadCount + jobUnreadCount));
    dispatch(
      setTabCounts({
        [ChannelQueryType.Couriers]: courierUnreadCount,
        [ChannelQueryType.JobChat]: jobUnreadCount,
        [ChannelQueryType.Activity]: activityUnreadCount,
      }),
    );
  }, [dispatch, getUnreadMentionsCount, getUnreadMessageCount]);


  const handleUpdateChannel = useCallback(
    async (channel: BaseChannel) => {
      console.log('channel', channel);
      if (!channel.isGroupChannel() || !userId) return;
      if (queryType === ChannelQueryType.JobChat && showOwned) {
        const isOwned = await isChannelOwnedByUser(channel, userId);
        if (!isOwned) return;
      }
      const updatedChannel = await createNewChannelFromSendbirdChannel(channel, true);
      if (updatedChannel) {
        setChannelData(prev => {
          const channelToUpdateIndex = prev.channelInformation.findIndex(chan => chan.channelUrl === channel.url);
          const updatedChannelInfo = [...prev.channelInformation];
          updatedChannelInfo[channelToUpdateIndex] = updatedChannel;

          return {
            ...prev,
            channelInformation: updatedChannelInfo,
          };
        });
        updateUnreadTabs();
      }
    },
    [queryType, setChannelData, showOwned, userId, updateUnreadTabs],
  );


//EVENT HANDLERS

  const setupChannelHandlers = useCallback(() => {
    if (typeof sdk === 'undefined' || !sdk?.groupChannel) {
      return;
    }
    const generalChannelHandler = new GroupChannelHandler();

    const customTypeChannelHandler = new GroupChannelHandler();

    removeChannelHandlers();
    console.log('setting up new handlers');

    sdk.groupChannel.addGroupChannelHandler('channel_handler_general', generalChannelHandler);
    generalChannelHandler.onChannelChanged = (channel: BaseChannel) => handleUpdateChannel(channel);
    generalChannelHandler.onUserJoined = (channel, user) => handleChannelJoined(channel, user, setChannelData);
    generalChannelHandler.onUserLeft = (channel, user) => handleChannelLeft(channel, user, setChannelData);
    generalChannelHandler.onMessageReceived = (channel, message) =>
      handleMessageReceived(channel, message, currentChannelUrl);

    sdk.groupChannel.addGroupChannelHandler('channel_handler_archived', customTypeChannelHandler);
    customTypeChannelHandler.onChannelChanged = (channel: BaseChannel) => handleUpdateChannelCustomType(channel);

    dispatch(setIsChannelDataLoading(false));
    dispatch(setChannelDataInvalidated(false));
  }, [
    sdk,
    currentChannelUrl,
    removeChannelHandlers,
    dispatch,
    handleUpdateChannel,
    handleChannelJoined,
    setChannelData,
    handleChannelLeft,
    handleMessageReceived,
    handleUpdateChannelCustomType,
  ]);



  
  const setupConnectionHandlers = useCallback(() => {
    if (
      userId === null ||
      typeof userId === 'undefined' ||
      typeof sdk === 'undefined' ||
      sdk === null ||
      Object.entries(sdk).length === 0
    ) {
      return;
    }

    const filter =
      queryType === ChannelQueryType.Unread ||
      queryType === ChannelQueryType.Search ||
      queryType === ChannelQueryType.Activity
        ? ChannelQueryType.All
        : queryType;

    const params = {
      [GetChannelQueryParams.Type]: filter,
      [GetChannelQueryParams.PageSize]: CHANNELS_PER_PAGE,
      [GetChannelQueryParams.ShowUnreadMessages]: queryType === ChannelQueryType.Unread,
      [GetChannelQueryParams.UserId]: userId,
    };

    const connectionHandler = new ConnectionHandler();
    sdk?.removeConnectionHandler('connection_handler');
    sdk.addConnectionHandler('connection_handler', connectionHandler);

    connectionHandler.onConnected = async () => {
      dispatch(setIsActivitiesInvalidated(true));
    };
    connectionHandler.onReconnectSucceeded = async () => {
      dispatch(setIsActivitiesInvalidated(true));
      const channels = await handleFetchChannels(params, false);
      if (channels) {
        dispatch(setIsTabDataLoaded(false));
        updateUnreadTabs();
        const channel = await sdk.groupChannel.getChannel(currentChannelUrl);
        channel?.refresh();
      }
    };
  }, [currentChannelUrl, dispatch, handleFetchChannels, queryType, sdk, updateUnreadTabs, userId]);

  useEffect(() => {
    setupConnectionHandlers();
  });

    useEffect(() => {
    setupConnectionHandlers();
  });

  useEffect(() => {
    if (
      typeof sdk === 'undefined' ||
      typeof sdk?.groupChannel === 'undefined' ||
      !sdk?.groupChannel === null
    ) {
      return;
    }
    if (channelDataInvalidated) {
      setupChannelHandlers();
    }
  }, [channelData.channelInformation.length, channelDataInvalidated, sdk, setupChannelHandlers]);

  useEffect(() => {
    return () => {
      removeChannelHandlers();
      if (typeof sdk === 'undefined' || sdk === null || Object.entries(sdk).length === 0) {
        return;
      }
      sdk?.removeConnectionHandler('connection_handler');
    };
  }, [dispatch, removeChannelHandlers, sdk]);

// If problem, please fill out the below. If question, please delete.
[UIKit Version]
// What version of the SDK are you using?
@sendbird/uikit-react”: “^3.12.0”,
and the js sdk ,that the 3.12.0 ui-kit exposes
(“@sendbird/chat”: “^4.10.9”)

[Reproduction Steps]
The whole application works correctly, until a disconnect and a successful reconnect occurs. The problem is, if the user lost internet connection, and received new messages in the chat, that is not currently open (Channel-1), then the following ensues:

  1. the onReconnectSucceeded method fires, the channel list is fetched from our backend, and displays the correct information for all the channels ( in particular the unreadMessageCount for all channels is correct (Channel-1 included)).
    2.if the user receives some new messages in Channel-1, then the onChannelChanged method fires, and the channel.unreadMessageCount in the ‘handleUpdateChannel’ function is missing the amount of messages, that were received, while the user had no internet connection.
    (F.E.)
    1.user has internet connnection, receives one message, but does not read it.
  2. user looses connection.
  3. user receives 3 more messages.
  4. user regains connection.
  5. 4 is displayed in the channel preview for unreadMessages.
  6. user receives one more message.
  7. the channel.unreadMessageCount in ‘handleUpdateChannel’ is 2, we update the channel preview unreadMessageCount to 2, which is incorrect.

Another thing, is that updateUnreadTabs will display correct unreadMessageCount.

On further investigation I found, that If i force the rerender of SendbirdProvider, in the onReconnectSucceeded handler, (by generating a random key for SendbirdProvider), then the whole app refreshes, but the bug is gone. ( So I think, the GroupChannelHandler somehow does not update the refference for the channel in memory, upon recconectSucceded event).

[Frequency]
100%

[Current impact]
After reconnecting the user sometimes sees wrong unreadMessageCount in channelList (depends if he received messages while offline)