# 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
        ```
