1
1
'use client'
2
2
3
- import { ChangeEventHandler , FC , useCallback , useMemo , useState , useTransition } from 'react'
3
+ import {
4
+ ChangeEventHandler ,
5
+ FC ,
6
+ useCallback ,
7
+ useEffect ,
8
+ useMemo ,
9
+ useState ,
10
+ useTransition ,
11
+ } from 'react'
4
12
5
13
import { LoadingState } from '@baseapp-frontend/design-system/components/web/displays'
6
14
import { Searchbar as DefaultSearchbar } from '@baseapp-frontend/design-system/components/web/inputs'
@@ -28,6 +36,7 @@ const ChatRoomsList: FC<ChatRoomsListProps> = ({
28
36
VirtuosoProps = { } ,
29
37
} ) => {
30
38
const [ tab , setTab ] = useState < ChatTabValues > ( CHAT_TAB_VALUES . active )
39
+ const [ renderList , setRenderList ] = useState < boolean > ( true )
31
40
32
41
const [ isRefetchPending , startRefetchTransition ] = useTransition ( )
33
42
const { data, loadNext, isLoadingNext, hasNext, refetch } = useRoomsList (
@@ -44,39 +53,53 @@ const ChatRoomsList: FC<ChatRoomsListProps> = ({
44
53
const handleSearchChange : ChangeEventHandler < HTMLInputElement > = ( e ) => {
45
54
const value = e . target . value || ''
46
55
startTransition ( ( ) => {
47
- refetch ( {
48
- q : value ,
49
- unreadMessages : isInUnreadTab ,
50
- archived : isInArchivedTab ,
51
- } )
56
+ refetch (
57
+ {
58
+ q : value ,
59
+ unreadMessages : isInUnreadTab ,
60
+ archived : isInArchivedTab ,
61
+ } ,
62
+ { fetchPolicy : 'network-only' } ,
63
+ )
52
64
} )
53
65
}
54
66
55
67
const handleSearchClear = ( ) => {
56
68
startTransition ( ( ) => {
57
69
reset ( )
58
- refetch ( {
59
- q : '' ,
60
- unreadMessages : isInUnreadTab ,
61
- archived : isInArchivedTab ,
62
- } )
70
+ refetch (
71
+ {
72
+ q : '' ,
73
+ unreadMessages : isInUnreadTab ,
74
+ archived : isInArchivedTab ,
75
+ } ,
76
+ { fetchPolicy : 'network-only' } ,
77
+ )
63
78
} )
64
79
}
65
80
66
81
const handleChange = ( event : React . SyntheticEvent , newTab : string ) => {
67
82
setTab ( newTab as ChatTabValues )
68
83
startRefetchTransition ( ( ) => {
84
+ setRenderList ( false )
69
85
refetch (
70
86
{
71
87
q : searchValue ,
72
88
unreadMessages : newTab === CHAT_TAB_VALUES . unread ,
73
89
archived : newTab === CHAT_TAB_VALUES . archived ,
74
90
} ,
75
- { fetchPolicy : 'store-and- network' } ,
91
+ { fetchPolicy : 'network-only ' } ,
76
92
)
77
93
} )
78
94
}
79
95
96
+ // Virtuoso has a bug where it does not recognize endReached if the data is changed while the component is still mounted.
97
+ // The `renderList` state is a workaround to force the component to dismount and remount,
98
+ // to ensure that Virtuoso will recognized endReached everytime the tab is changed
99
+ useEffect ( ( ) => {
100
+ setRenderList ( true )
101
+ } , [ data ] )
102
+
80
103
const { id : selectedRoom , setChatRoom } = useChatRoom ( )
81
104
const chatRooms = useMemo (
82
105
( ) => data ?. chatRooms ?. edges ?. filter ( ( edge ) => edge ?. node ) . map ( ( edge ) => edge ?. node ) || [ ] ,
@@ -126,29 +149,14 @@ const ChatRoomsList: FC<ChatRoomsListProps> = ({
126
149
)
127
150
128
151
const renderListContent = ( ) => {
129
- const emptyChatRoomsList = chatRooms . length === 0
130
-
131
- if ( ! isPending && searchValue && emptyChatRoomsList ) return < SearchNotFoundState />
152
+ const hasEmptyStates = ! isPending && chatRooms . length === 0
132
153
133
- if ( ! isPending && emptyChatRoomsList ) return < EmptyChatRoomsState />
154
+ if ( hasEmptyStates ) {
155
+ if ( searchValue ) return < SearchNotFoundState />
156
+ return < EmptyChatRoomsState />
157
+ }
134
158
135
- return (
136
- < Virtuoso
137
- data = { chatRooms }
138
- overscan = { 1 }
139
- itemContent = { ( _index , item ) => renderItem ( item ) }
140
- style = { { scrollbarWidth : 'none' } }
141
- components = { {
142
- Footer : renderLoadingState ,
143
- } }
144
- endReached = { ( ) => {
145
- if ( hasNext ) {
146
- loadNext ( 5 )
147
- }
148
- } }
149
- { ...VirtuosoProps }
150
- />
151
- )
159
+ return undefined
152
160
}
153
161
154
162
return (
@@ -194,6 +202,23 @@ const ChatRoomsList: FC<ChatRoomsListProps> = ({
194
202
< Tab label = { renderTabLabel ( CHAT_TAB_VALUES . archived ) } value = { CHAT_TAB_VALUES . archived } />
195
203
</ Tabs >
196
204
{ renderListContent ( ) }
205
+ { renderList && (
206
+ < Virtuoso
207
+ data = { chatRooms }
208
+ overscan = { 1 }
209
+ itemContent = { ( _index , item ) => renderItem ( item ) }
210
+ style = { { scrollbarWidth : 'none' } }
211
+ components = { {
212
+ Footer : renderLoadingState ,
213
+ } }
214
+ endReached = { ( ) => {
215
+ if ( hasNext ) {
216
+ loadNext ( 5 )
217
+ }
218
+ } }
219
+ { ...VirtuosoProps }
220
+ />
221
+ ) }
197
222
</ ChatRoomListContainer >
198
223
)
199
224
}
0 commit comments