# Web UIKit v3.0 Migration Guide

## Major breaking changes

* @amityco/js-sdk is no longer support
* The UIKit is now based on @amityco/ts-sdk is no longer support
* TypeScript support for Social/Chat Components
* remove children component as a function, render-props
* drop props-types support
* custom components config and post renderer config have been changed from

```
{
  [componentName: string]: ReactComponent
}  
```

to

```
{
  [componentName: string]: (props: componentProps) => ReactNode
}  
```

### **Deprecated functions**

* components
  * FileUploader \[src/core/components/Uploaders/Uploader.jsx]
    * use useFileUpload instead
  * LoadMore \[src/social/components/LoadMore/index.jsx]
    * use LoadMoreWrapper instead
* hoc
  * withSize \[src/core/hocs/withSize.jsx]
    * useSize instead
  * withSDK \[src/core/hocs/withSDK.jsx]
    * useSDK instead
* hooks
  * useAsyncCallback \[src/core/hooks/useAsyncCallback.ts]
    * ```
      const [isSubmitting, setIsSubmitting] = useState(false)
      const onSubmit = async () => {
        try {
          setIsSubmitting(true)
          // callback code
        } finally {
          setIsSubmitting(false);
        }
      }
      ```
  * useElement \[src/core/hooks/useElement.ts]
    * ```
      const [ref, element] = useElement()

      <div ref={ref} />
      ```

      is equivalent to

      ```
      const elementRef = useRef<HTMLDivElement | null>(null)
      // element is elementRef.current
      <div ref={elementRef} />
      ```
  * useFollow \[src/core/hooks/useFollow\.ts]
    * for isFollowNone, isFollowAccepted, isFollowPending it can be replaced by useFollowStatus like this
    * ```
      const followStatus = useFollowStatus(sourceUserId)

      const isFollowNone = followStatus === 'none'
      const isFollowAccepted = followStatus === 'accepted'
      const isFollowPending = followStatus === 'pending'
      ```
    * for follow, followAccept, followDecline, deleteFollower just call a UserRepository.Relationship directly

      ```
      const follow = UserRepository.Relationship.follow
      const followAccept = UserRepository.Relationship.acceptMyFollower
      const followDecline = UserRepository.Relationship.declineMyFollower
      const deleteFollower = UserRepository.Relationship.unfollow
      ```
  * useCommentLike \[src/social/hooks/useCommentLike.js]\
    it can be replaced like this
* ```
  const isLiked = !!(
    comment &&
    comment.myReactions &&
    comment.myReactions.includes(LIKE_REACTION_KEY)
  );
  const totalLikes = comment?.reactions[LIKE_REACTION_KEY] || 0;

  const handleToggleLike = async () => {
    if (comment == null) return;
    try {
      if (!isLiked) {
        await ReactionRepository.addReaction('comment', comment.commentId, LIKE_REACTION_KEY);
        onLikeSuccess?.(comment);
      } else {
        await ReactionRepository.removeReaction('comment', comment.commentId, LIKE_REACTION_KEY);
        onUnlikeSuccess?.(comment);
      }
    } catch (_error) {
      console.error("Can't toggle like", _error);
    }
  };  
  ```

  * useCommunityMembers \[src/social/hooks/useCommunityMembers.ts]

  ```
  use useCommunityMembersCollection and useCommunityModeratorsCollection instead
  ```

  * useCommunityOneMember \[src/social/hooks/useCommunityOneMember.ts]

  ```
  currentMember = const currentMember = members.find((member) => member.userId === currentUserId);


  const isCommunityModerator = isModerator(currentMember?.roles);
  const hasModeratorPermissions =
    (isCommunityMember(currentMember) && isCommunityModerator) ||
    isModerator(user?.roles) ||
    isAdmin(user?.roles);

  for members use useCommunityMembersCollection instead
  for permission related use useCommunityPermission instead
  ```
* usePostChildren \[src/social/hooks/usePostChildren.ts]
  * use usePostByIds instead
* usePostLike \[src/social/hooks/usePostLike.ts]

  ```
  function isPostLikedByMe(post?: Amity.Post) {
    if (post == null || post.myReactions?.length === 0) return false;
    return post?.myReactions?.includes(LIKE_REACTION_KEY);
  }

    const [isActive, setIsActive] = useState(isPostLikedByMe(post));
  useEffect(() => {
    setIsActive(isPostLikedByMe(post));
  }, [post?.myReactions]);

  const handleToggleLike = async () => {
    if (post == null) return;
    if (!isActive) {
      await ReactionRepository.addReaction('post', post.postId, LIKE_REACTION_KEY);
      onLikeSuccess?.(post);
      setIsActive(!isActive);
    } else {
      await ReactionRepository.removeReaction('post', post.postId, LIKE_REACTION_KEY);
      onUnlikeSuccess?.(post);
      setIsActive(!isActive);
    }
  };
  ```
* useReport \[src/social/hooks/useReport.ts]
  * use useUserFlaggedByMe instead
* useChannelMembers \[src/chat/hooks/useChannelMembers.ts] -> useChannelMembersCollection
  * return values \[channelMembers, hasMore, loadMore] to {channelMembers, isLoading, loadMore, hasMore, loadMoreHasBeenCalled }
* useChannels \[src/chat/hooks/useChannels.ts] -> useChannelsCollection
  * return values \[channels, hasMore, loadMore] to {channels, isLoading, loadMore, hasMore, loadMoreHasBeenCalled }
* useMessages \[src/chat/hooks/useMessages.ts] -> useMessagesCollection
  * return values \[messages, hasMore, loadMore] to {messages, isLoading, loadMore, hasMore, loadMoreHasBeenCalled }
* useAllUsers \[src/core/hooks/useAllUsers.ts] -> useAllUsersCollection
  * return values \[users, hasMore, loadMore] to {users, isLoading, loadMore, hasMore, loadMoreHasBeenCalled }
* useFollowers \[src/core/hooks/useFollowers.ts] -> useFollowersCollectionCollection
  * return values \[followers, hasMore, loadMore] to {followers, isLoading, loadMore, hasMore, loadMoreHasBeenCalled }
* useFollowings \[src/core/hooks/useFollowings.ts] -> useFollowingsCollectionCollection
  * return values \[followings, hasMore, loadMore] to {followings, isLoading, loadMore, hasMore, loadMoreHasBeenCalled }
* useUserQuery \[src/core/hooks/useUserQuery.ts] -> useUsersCollection
  * return values \[users, hasMore, loadMore] to {users, isLoading, loadMore, hasMore, loadMoreHasBeenCalled }
* useCategories \[src/social/hooks/useCategories.ts] -> useCategoriesCollection
  * return values \[categories, hasMore, loadMore] to {categories, isLoading, loadMore, hasMore, loadMoreHasBeenCalled }
* useCommunities \[src/social/hooks/useCommunities.ts] -> useCommunitiesCollection
  * return values \[communities, hasMore, loadMore] to {communities, isLoading, loadMore, hasMore, loadMoreHasBeenCalled }
* useMedia \[src/social/hooks/useMedia.ts] -> useMediaCollection
  * return values \[media, hasMore, loadMore] to {media, isLoading, loadMore, hasMore, loadMoreHasBeenCalled }
* usePosts \[src/social/hooks/usePosts.ts] -> usePostsCollection
  * return values \[posts, hasMore, loadMore] to {posts, isLoading, loadMore, hasMore, loadMoreHasBeenCalled }
* useRecommendedCommunities \[src/social/hooks/useRecommendedCommunities.ts] -> useRecommendedCommunitiesCollection
  * return values \[posts, hasMore, loadMore] to {posts, isLoading, loadMore, hasMore, loadMoreHasBeenCalled }
* useTrendingCommunities \[src/social/hooks/useTrendingCommunities.ts] -> useTrendingCommunitiesCollection
  * return values \[posts, hasMore, loadMore] to {posts, isLoading, loadMore, hasMore, loadMoreHasBeenCalled }
* functions
  * isEmpty \[src/helpers/isEmpty.js]\
    just use javascript equal syntax instead
  * isEqual \[src/helpers/isEqual.js]\
    just use javascript equal syntax instead
  * isPostModerator \[src/helpers/utils.ts]\
    use usePostPermission instead
  * canEditCommunity \[src/helpers/utils.ts]\
    use usePostPermission instead
  * canDeletePost \[src/helpers/utils.ts]\
    use usePostPermission instead
  * canEditPost \[src/helpers/utils.ts]\
    use usePostPermission instead
  * canReportPost \[src/helpers/utils.ts]\
    use usePostPermission instead
  * promisify \[src/helpers/promisify.ts]

    ```
    use node promisify instead or
    const promise = new Promise((resolve, reject) => {
      fn(function callback(data) => {
        resolve(data)
      })
    })
    ```
  * stripUndefinedValues \[src/helpers/utils.ts]

    ```
    export function stripUndefinedValues<T extends object>(obj: T): Partial<T> {
      const result: Partial<T> = {};
      
      Object.entries(obj).forEach(([key, value]) => {
        if (value !== undefined) {
          result[key as keyof T] = value;
        }
      });
      
      return result;
    }
    ```

## **Breaking changes functions**

**Opcomponents**

* CommentList \[src/social/components/CommentList/index.tsx]
  * props filterByParentId is removed
* hooks
  * useFollowStatus \[src/core/hooks/useFollowStatus.ts]
    * parameters (sourceUserId, targetUserId) to (sourceUserId)
  * useChannelMembers \[src/chat/hooks/useChannelMembers.ts]
    * parameters (channelId, memberCount) to (channelId)
    * return values \[members, hasMore, loadMore] to {channelMembers, isLoading, loadMore, hasMore, loadMoreHasBeenCalled }
  * useCommentsQuery \[src/core/hooks/useCommentsQuery] -> useCommentsCollection
    * parameters
      * limit has been added
      * first and last have been removed
  * useCommunity \[src/core/hooks/useCommunity]
    * parameters resolver has been removed
    * return values
      * ```
        {
            community,
        	file,
            communityCategories,
        	joinCommunity,
            leaveCommunity,
            updateCommunity,
        	closeCommunity,
        }
        ```

        to
      * ```
        community
        ```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.social.plus/developers/migration-guides/web-uikit-v3.0-migration-guide.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
