diff --git a/packages/components/modules/messages/web/ChatRoomsList/index.tsx b/packages/components/modules/messages/web/ChatRoomsList/index.tsx index c21e2563..fdc6a92b 100644 --- a/packages/components/modules/messages/web/ChatRoomsList/index.tsx +++ b/packages/components/modules/messages/web/ChatRoomsList/index.tsx @@ -1,6 +1,14 @@ 'use client' -import { ChangeEventHandler, FC, useCallback, useMemo, useState, useTransition } from 'react' +import { + ChangeEventHandler, + FC, + useCallback, + useEffect, + useMemo, + useState, + useTransition, +} from 'react' import { LoadingState } from '@baseapp-frontend/design-system/components/web/displays' import { Searchbar as DefaultSearchbar } from '@baseapp-frontend/design-system/components/web/inputs' @@ -28,6 +36,7 @@ const ChatRoomsList: FC = ({ VirtuosoProps = {}, }) => { const [tab, setTab] = useState(CHAT_TAB_VALUES.active) + const [renderList, setRenderList] = useState(true) const [isRefetchPending, startRefetchTransition] = useTransition() const { data, loadNext, isLoadingNext, hasNext, refetch } = useRoomsList( @@ -44,39 +53,53 @@ const ChatRoomsList: FC = ({ const handleSearchChange: ChangeEventHandler = (e) => { const value = e.target.value || '' startTransition(() => { - refetch({ - q: value, - unreadMessages: isInUnreadTab, - archived: isInArchivedTab, - }) + refetch( + { + q: value, + unreadMessages: isInUnreadTab, + archived: isInArchivedTab, + }, + { fetchPolicy: 'network-only' }, + ) }) } const handleSearchClear = () => { startTransition(() => { reset() - refetch({ - q: '', - unreadMessages: isInUnreadTab, - archived: isInArchivedTab, - }) + refetch( + { + q: '', + unreadMessages: isInUnreadTab, + archived: isInArchivedTab, + }, + { fetchPolicy: 'network-only' }, + ) }) } const handleChange = (event: React.SyntheticEvent, newTab: string) => { setTab(newTab as ChatTabValues) startRefetchTransition(() => { + setRenderList(false) refetch( { q: searchValue, unreadMessages: newTab === CHAT_TAB_VALUES.unread, archived: newTab === CHAT_TAB_VALUES.archived, }, - { fetchPolicy: 'store-and-network' }, + { fetchPolicy: 'network-only' }, ) }) } + // Virtuoso has a bug where it does not recognize endReached if the data is changed while the component is still mounted. + // The `renderList` state is a workaround to force the component to dismount and remount, + // to ensure that Virtuoso will recognized endReached everytime the tab is changed + useEffect(() => { + setRenderList(true) + }, [data]) + const { id: selectedRoom, setChatRoom } = useChatRoom() const chatRooms = useMemo( () => data?.chatRooms?.edges?.filter((edge) => edge?.node).map((edge) => edge?.node) || [], @@ -126,29 +149,14 @@ const ChatRoomsList: FC = ({ ) const renderListContent = () => { - const emptyChatRoomsList = chatRooms.length === 0 - - if (!isPending && searchValue && emptyChatRoomsList) return + const hasEmptyStates = !isPending && chatRooms.length === 0 - if (!isPending && emptyChatRoomsList) return + if (hasEmptyStates) { + if (searchValue) return + return + } - return ( - renderItem(item)} - style={{ scrollbarWidth: 'none' }} - components={{ - Footer: renderLoadingState, - }} - endReached={() => { - if (hasNext) { - loadNext(5) - } - }} - {...VirtuosoProps} - /> - ) + return undefined } return ( @@ -194,6 +202,23 @@ const ChatRoomsList: FC = ({ {renderListContent()} + {renderList && ( + renderItem(item)} + style={{ scrollbarWidth: 'none' }} + components={{ + Footer: renderLoadingState, + }} + endReached={() => { + if (hasNext) { + loadNext(5) + } + }} + {...VirtuosoProps} + /> + )} ) }