Post live object isn't updated when new comment is added to post

Hi there,

I’m using open-source web UIKit v3.11.6 and I’ve noticed that the usePost() hook does not fetch the updated post when a comment is added to it.

It does, however, fetch the updated post when I like/unlike the post (and with it, the new comments).

I’ve seen similar topics in this forum, but none of the solutions appear to work for this.

I’ve hit a wall so any help you can provide would be greatly appreciated.

Many thanks,
Noah

Hello @noahatcavern , Our team recommends upgrading to UIKit v4.2.0, as this may resolve the issue you’re experiencing with usePost().

You can find the latest version here:
:pushpin: GitHub - AmityCo/Amity-Social-Cloud-UIKit-Web-OpenSource: Amity Social Cloud offers Chat and Social SDKs to streamline app development. Dive into our UI Kits and sample apps in our repositories to spark your creativity. To learn more, visit amity.co.

Let us know if you need further assistance!

Unfortunately, upgrading would be a big effort for us due to our UI customizations, so we can’t at the moment. That said, we will upgrade in the future - we just need this bug resolved for our users as soon as possible.

Could you please point me to areas of the v4.2.0 code that would solve this particular issue? I will attempt to cherry pick it so we can resolve this bug.

Thank you,
Noah

Hello @noahatcavern, thank you for sharing the details.

To better understand the issue, could you clarify which specific data fields are not updating when fetching the post? Additionally, would it be possible to provide a screen recording demonstrating the issue? This will help our team investigate further and provide more targeted guidance.

Looking forward to your response.

Hi there! I also have a problem with live updates. When I add the new comment using dashboard, I get new comment on the frontend because of live collection and getUserTopic subscriptions, but it doesn’t increment the commentsCount on the post. Should it work this way?

1 Like

Hello @Arseniiy , thank you for reaching out.

Could you confirm if there are any errors occurring? Additionally, please provide the following details to help us investigate further:

  • SDK version you are using
  • Implementation code related to how you are handling live updates

This information will help us better understand the issue and assist you accordingly.

I use "@amityco/ts-sdk: "^6.35.0". To handle the live updates I use a couple of hooks based on the useLiveCollection hook. At the moment, I’ve added a trick that allows me to refetch the data associated with posts, but it doesn’t look like the best approach because I need to flush all subscriptions associated with the post.

import { subscribeTopic } from '@amityco/ts-sdk';
import { useRef, useMemo, useEffect, useCallback } from 'react';
import { hashKey, useQuery, useQueryClient } from '@tanstack/react-query';

import { useSubscriptionsStore } from '../store/subscriptions-store';

export function useLiveCollection<TCallback, TParams>({
  fetcher,
  params,
  queryKey,
  callback = () => {},
  shouldCall = () => true,
  getSubscribedTopic,
}: {
  fetcher: (
    params: Amity.LiveCollectionParams<TParams>,
    callback: Amity.LiveCollectionCallback<TCallback>
  ) => Amity.Unsubscriber;
  params: Amity.LiveCollectionParams<TParams>;
  queryKey: string[];
  callback?: Amity.LiveCollectionCallback<TCallback>;
  shouldCall?: () => boolean;
  queryFn?: () => Promise<TCallback[]>;
  getSubscribedTopic?: () => string;
}): {
  items: TCallback[];
  isLoading: boolean;
  hasMore: boolean;
  loadMore: () => void;
  error: Error | null;
} {
  const queryClient = useQueryClient();
  const { subscribe, getSubscriptionsByKey } = useSubscriptionsStore();
  const loadMoreFnRef = useRef<(() => void) | null>(null);
  const isSubscribed = useMemo(
    () => getSubscriptionsByKey(hashKey(queryKey)).length > 0,
    [getSubscriptionsByKey, queryKey]
  );

  const loadMore = useCallback(() => {
    loadMoreFnRef.current?.();
  }, []);

  const callbackFn: Amity.LiveCollectionCallback<TCallback> = useCallback(
    (response) => {
      if (!shouldCall()) return;
      const responseData = Array.isArray(response.data) ? response.data : [response.data];
      const oldData = queryClient.getQueryData<{ items: TCallback[] }>(queryKey);

      queryClient.setQueryData(queryKey, {
        items: responseData.length > 0 ? responseData : oldData?.items || [],
        isLoading: false,
        hasMore: response.hasNextPage,
        error: response.error,
      });

      loadMoreFnRef.current = response.onNextPage || null;
      callback(response);
    },
    [queryClient, queryKey, shouldCall, callback]
  );

  useEffect(() => {
    if (!shouldCall() || isSubscribed) return;

    const unsubscriber = fetcher(params, callbackFn);
    subscribe(hashKey(queryKey), unsubscriber);

    if (getSubscribedTopic) {
      try {
        const topicUnsubscriber = subscribeTopic(getSubscribedTopic());
        subscribe(hashKey(queryKey), topicUnsubscriber);
      } catch (error) {
        console.error(error);
      }
    }
  }, [
    params,
    shouldCall,
    fetcher,
    callbackFn,
    subscribe,
    queryKey,
    getSubscribedTopic,
    isSubscribed,
  ]);

  const { data } = useQuery({
    queryKey,
    initialData: {
      items: [],
      isLoading: true,
      hasMore: false,
      error: null,
    },
    staleTime: 0,
    gcTime: 1000 * 60 * 60 * 24 * 5,
    refetchOnWindowFocus: false,
    refetchOnMount: false,
    refetchOnReconnect: false,
    refetchInterval: false,
    refetchIntervalInBackground: false,
  });

  return {
    items: data.items,
    isLoading: data.isLoading,
    hasMore: data.hasMore,
    loadMore,
    error: data.error,
  };
}

import { getUserTopic, PostRepository, SubscriptionLevels } from '@amityco/ts-sdk';

import { useLiveCollection } from 'src/socials/shared/hooks/use-live-collection';

import { useGetUserQuery } from '../../users/api/get-user';

export type UseGetPostsQueryProps = {
  userId: string;
  targetId: string;
};

export const useGetPostsQuery = ({ userId, targetId }: UseGetPostsQueryProps) => {
  const { user } = useGetUserQuery({ userId });

  const {
    items: posts,
    isLoading,
    error,
    hasMore,
    loadMore,
  } = useLiveCollection<Amity.Post, any>({
    fetcher: PostRepository.getPosts,
    params: {
      targetId,
      targetType: 'user',
      sortBy: 'lastCreated',
      limit: 3,
    },
    queryKey: ['posts', targetId],
    shouldCall: () => !!targetId && !!user,
    getSubscribedTopic: () => {
      if (!user) throw new Error('User not found');
      return getUserTopic(user, SubscriptionLevels.POST);
    },
  });

  return {
    posts,
    loading: isLoading,
    error,
    hasMore,
    loadMore,
  };
};
import { hashKey } from '@tanstack/react-query';
import { getUserTopic, CommentRepository, SubscriptionLevels } from '@amityco/ts-sdk';

import { useLiveCollection } from 'src/socials/shared/hooks/use-live-collection';
import { useSubscriptionsStore } from 'src/socials/shared/store/subscriptions-store';

import { useGetUserQuery } from '../../users/api/get-user';

export type UseGetCommentsQueryProps = {
  userId: string;
  referenceId: string;
  referenceType: Amity.CommentReferenceType;
};

export const useGetCommentsQuery = ({
  userId,
  referenceId,
  referenceType,
}: UseGetCommentsQueryProps) => {
  const { user } = useGetUserQuery({ userId });
  const { unsubscribe, getSubscriptionsByKey } = useSubscriptionsStore();

  const {
    items: comments,
    isLoading,
    error,
    hasMore,
    loadMore,
  } = useLiveCollection<Amity.Comment, any>({
    fetcher: CommentRepository.getComments,
    params: {
      referenceId,
      referenceType,
      sortBy: 'lastCreated',
      limit: 3,
    },
    queryKey: ['comment', referenceId, referenceType],
    shouldCall: () => !!referenceId && !!user,
    callback: (response) => {
      if (response.data) {
        const postKey = hashKey(['posts', userId]);
        const hasSubscriptions = getSubscriptionsByKey(postKey).length > 0;
        if (hasSubscriptions) {
          unsubscribe(postKey);
        }
      }
    },
    getSubscribedTopic: () => {
      if (!user) throw new Error('User not found');
      return getUserTopic(user, SubscriptionLevels.COMMENT);
    },
  });

  return {
    comments,
    loading: isLoading,
    error,
    hasMore,
    loadMore,
  };
};
1 Like

Hi @SocialPlus_Support

In the post object, the “comments”, “commentsCount”, and “latestComments” data fields are not being updated when a new comment is added.

I’ve recorded what it looks like between two instances of our site. You’ll see that reactions are updating but the comments are not.

It doesn’t allow me to upload the mp4 video file to this topic, but I uploaded it to WeTransfer here: https://we.tl/t-HzjeOwS1nj

Thank you,
Noah

1 Like

Hello @noahatcavern @Arseniiy , Thank you for the update. We’ve shared it with our team and will keep you informed on the progress and findings.

Hello @Arseniiy , After checking with our team, the code for handling comment count follows the approach shown in the attached image. Please review your implementation and try again. Let us know if the issue persists.

Hello @noahatcavern, could you try updating the SDK to the latest version 6.35.0 in the UIKit package and retest? Also, please test in different web browsers, such as Chrome and Safari.

Hi @SocialPlus_Support. Am I right that getting real-time updates for a collection cannot help us in the given case and we should subscribe to updates related to an object (post in our case).

1 Like

Hi @Arseniiy, that’s correct. Please let us know if you have any further questions.