Skip to content

Commit ea63ae2

Browse files
Custom channellist filter (#678)
* adds optional prop to ChannelList for a custom filter on channels * adds prop type * remove debug * updates test * updates proptype * cleanup on types * cleanup * rename channelListFilterFunction Co-authored-by: Amin Mahboubi <[email protected]>
1 parent 382cd6a commit ea63ae2

File tree

3 files changed

+49
-2
lines changed

3 files changed

+49
-2
lines changed

src/components/ChannelList/ChannelList.js

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,10 @@ const ChannelList = (props) => {
118118
activeChannelHandler,
119119
);
120120

121+
const loadedChannels = props.channelRenderFilterFn
122+
? props.channelRenderFilterFn(channels)
123+
: channels;
124+
121125
useMobileNavigation(channelListRef, navOpen, closeMobileNav);
122126

123127
// All the event listeners
@@ -216,13 +220,13 @@ const ChannelList = (props) => {
216220
LoadingIndicator={LoadingIndicator}
217221
LoadingErrorIndicator={LoadingErrorIndicator}
218222
>
219-
{!channels || channels.length === 0
223+
{!loadedChannels || loadedChannels.length === 0
220224
? renderEmptyStateIndicator()
221225
: smartRender(Paginator, {
222226
loadNextPage,
223227
hasNextPage,
224228
refreshing: status.refreshing,
225-
children: channels.map((item) => renderChannel(item)),
229+
children: loadedChannels.map(renderChannel),
226230
})}
227231
</List>
228232
);
@@ -352,6 +356,13 @@ ChannelList.propTypes = {
352356
* @param {Event} event [Event object](https://getstream.io/chat/docs/event_object/?language=js) corresponding to `channel.deleted` event
353357
* */
354358
onChannelDeleted: PropTypes.func,
359+
/**
360+
* Optional function to filter channels prior to loading in the DOM. Do not use any complex or async logic here that would significantly delay the loading of the ChannelList.
361+
* We recommend using a pure function with array methods like filter/sort/reduce.
362+
* @param {Array} channels
363+
* @returns {Array} channels
364+
* */
365+
channelRenderFilterFn: /** @type {PropTypes.Validator<(channels: import('stream-chat').Channel[]) => import('stream-chat').Channel[]>} */ (PropTypes.func),
355366
/**
356367
* Object containing query filters
357368
* @see See [Channel query documentation](https://getstream.io/chat/docs/query_channels/?language=js) for a list of available fields for filter.

src/components/ChannelList/__tests__/ChannelList.test.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,37 @@ describe('ChannelList', () => {
176176
});
177177
});
178178

179+
it('should only show filtered channels when a filter function prop is provided', async () => {
180+
const filteredChannel = generateChannel({ channel: { type: 'filtered' } });
181+
182+
const customFilterFunction = (channels) => {
183+
return channels.filter((channel) => channel.type === 'filtered');
184+
};
185+
186+
const props = {
187+
filters: {},
188+
Preview: ChannelPreviewComponent,
189+
List: ChannelListComponent,
190+
channelRenderFilterFn: customFilterFunction,
191+
};
192+
193+
useMockedApis(chatClientUthred, [
194+
queryChannelsApi([filteredChannel, testChannel1]),
195+
]);
196+
197+
const { getByRole, queryAllByRole } = render(
198+
<Chat client={chatClientUthred}>
199+
<ChannelList {...props} />
200+
</Chat>,
201+
);
202+
203+
// Wait for list of channels to load in DOM.
204+
await waitFor(() => {
205+
expect(getByRole('list')).toBeInTheDocument();
206+
expect(queryAllByRole('listitem')).toHaveLength(1);
207+
});
208+
});
209+
179210
it('should render `LoadingErrorIndicator` when queryChannels api throws error', async () => {
180211
useMockedApis(chatClientUthred, [erroredGetApi()]);
181212
jest.spyOn(console, 'warn').mockImplementationOnce(() => null);

types/index.d.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,11 @@ export interface ChannelListProps {
322322
e: Client.Event,
323323
): void;
324324
setActiveChannelOnMount?: boolean;
325+
/**
326+
* Optional function to filter channels prior to loading in the DOM. Do not use any complex or async logic here that would significantly delay the loading of the ChannelList.
327+
* We recommend using a pure function with array methods like filter/sort/reduce.
328+
*/
329+
channelRenderFilterFn?: (channels: Client.Channel[]) => Client.Channel[];
325330
/** Object containing query filters */
326331
filters?: Client.ChannelFilters;
327332
/** Object containing query options */

0 commit comments

Comments
 (0)