Skip to content

Commit e5b528d

Browse files
authored
feat: use server-defined default limits for channel and channel lists (#2940)
### 🎯 Goal Removes the built-in defaults for channel and message limit in `queryChannels`. This allows for faster app load and smaller response sizes when SDK default filters are used. Ticket: https://linear.app/stream/issue/REACT-763/use-server-side-defined-default-limits-for-querychannels
1 parent 77be56c commit e5b528d

File tree

13 files changed

+112
-70
lines changed

13 files changed

+112
-70
lines changed

.nvmrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
lts/*
1+
24

examples/vite/src/App.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,13 @@ const filters: ChannelFilters = {
4848
type: 'messaging',
4949
archived: false,
5050
};
51-
const options: ChannelOptions = { limit: 5, presence: true, state: true };
51+
const options: ChannelOptions = {
52+
// limit: 10,
53+
// message_limit: 10,
54+
// member_limit: 10,
55+
presence: true,
56+
state: true,
57+
};
5258
const sort: ChannelSort = { pinned_at: 1, last_message_at: -1, updated_at: -1 };
5359

5460
// @ts-ignore

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,6 @@
112112
"i18next": "^25.2.1",
113113
"linkifyjs": "^4.3.2",
114114
"lodash.debounce": "^4.0.8",
115-
"lodash.defaultsdeep": "^4.6.1",
116115
"lodash.mergewith": "^4.6.2",
117116
"lodash.throttle": "^4.1.1",
118117
"lodash.uniqby": "^4.7.0",

src/components/Channel/Channel.tsx

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import React, {
1010
} from 'react';
1111
import clsx from 'clsx';
1212
import debounce from 'lodash.debounce';
13-
import defaultsDeep from 'lodash.defaultsdeep';
1413
import throttle from 'lodash.throttle';
1514
import type {
1615
APIErrorResponse,
@@ -65,7 +64,6 @@ import {
6564
import { CHANNEL_CONTAINER_ID } from './constants';
6665
import {
6766
DEFAULT_HIGHLIGHT_DURATION,
68-
DEFAULT_INITIAL_CHANNEL_PAGE_SIZE,
6967
DEFAULT_JUMP_TO_PAGE_SIZE,
7068
DEFAULT_NEXT_CHANNEL_PAGE_SIZE,
7169
DEFAULT_THREAD_PAGE_SIZE,
@@ -293,7 +291,7 @@ const ChannelInner = (
293291
activeUnreadHandler,
294292
allowConcurrentAudioPlayback,
295293
channel,
296-
channelQueryOptions: propChannelQueryOptions,
294+
channelQueryOptions,
297295
children,
298296
doDeleteMessageRequest,
299297
doMarkReadRequest,
@@ -308,16 +306,6 @@ const ChannelInner = (
308306
skipMessageDataMemoization,
309307
} = props;
310308

311-
const channelQueryOptions: ChannelQueryOptions & {
312-
messages: { limit: number };
313-
} = useMemo(
314-
() =>
315-
defaultsDeep(propChannelQueryOptions, {
316-
messages: { limit: DEFAULT_INITIAL_CHANNEL_PAGE_SIZE },
317-
}),
318-
[propChannelQueryOptions],
319-
);
320-
321309
const { client, customClasses, latestMessageDatesByChannels, mutes, searchController } =
322310
useChatContext('Channel');
323311
const { t } = useTranslationContext('Channel');

src/components/Channel/__tests__/Channel.test.js

Lines changed: 43 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,11 @@ describe('Channel', () => {
334334
it('should watch the current channel on mount', async () => {
335335
const watchSpy = jest.spyOn(channel, 'watch');
336336

337-
await renderComponent({ channel, chatClient });
337+
await renderComponent({
338+
channel,
339+
channelQueryOptions: { messages: { limit: 25 } },
340+
chatClient,
341+
});
338342

339343
await waitFor(() => {
340344
expect(watchSpy).toHaveBeenCalledTimes(1);
@@ -380,9 +384,12 @@ describe('Channel', () => {
380384
]);
381385
let hasMore;
382386
await act(() => {
383-
renderComponent({ channel, chatClient }, ({ hasMore: contextHasMore }) => {
384-
hasMore = contextHasMore;
385-
});
387+
renderComponent(
388+
{ channel, channelQueryOptions: { messages: { limit: 25 } }, chatClient },
389+
({ hasMore: contextHasMore }) => {
390+
hasMore = contextHasMore;
391+
},
392+
);
386393
});
387394

388395
await waitFor(() => {
@@ -395,9 +402,12 @@ describe('Channel', () => {
395402
queryChannelWithNewMessages(Array.from({ length: 25 }, generateMessage), channel),
396403
]);
397404
let hasMore;
398-
await renderComponent({ channel, chatClient }, ({ hasMore: contextHasMore }) => {
399-
hasMore = contextHasMore;
400-
});
405+
await renderComponent(
406+
{ channel, channelQueryOptions: { messages: { limit: 25 } }, chatClient },
407+
({ hasMore: contextHasMore }) => {
408+
hasMore = contextHasMore;
409+
},
410+
);
401411

402412
await waitFor(() => {
403413
expect(hasMore).toBe(true);
@@ -761,15 +771,21 @@ describe('Channel', () => {
761771
const limit = 10;
762772
it("should initiate the hasMore flag with the current message set's pagination hasPrev value", async () => {
763773
let hasMore;
764-
await renderComponent({ channel, chatClient }, ({ hasMore: hasMoreCtx }) => {
765-
hasMore = hasMoreCtx;
766-
});
774+
await renderComponent(
775+
{ channel, channelQueryOptions: { messages: { limit: 25 } }, chatClient },
776+
({ hasMore: hasMoreCtx }) => {
777+
hasMore = hasMoreCtx;
778+
},
779+
);
767780
expect(hasMore).toBe(true);
768781

769782
channel.state.messageSets[0].pagination.hasPrev = false;
770-
await renderComponent({ channel, chatClient }, ({ hasMore: hasMoreCtx }) => {
771-
hasMore = hasMoreCtx;
772-
});
783+
await renderComponent(
784+
{ channel, channelQueryOptions: { messages: { limit: 25 } }, chatClient },
785+
({ hasMore: hasMoreCtx }) => {
786+
hasMore = hasMoreCtx;
787+
},
788+
);
773789
expect(hasMore).toBe(false);
774790
});
775791
it('should be able to load more messages', async () => {
@@ -779,7 +795,7 @@ describe('Channel', () => {
779795
const newMessages = [generateMessage()];
780796

781797
await renderComponent(
782-
{ channel, chatClient },
798+
{ channel, channelQueryOptions: { messages: { limit: 25 } }, chatClient },
783799
({ loadMore, messages: contextMessages }) => {
784800
if (!contextMessages.find((message) => message.id === newMessages[0].id)) {
785801
// Our new message is not yet passed as part of channel context. Call loadMore and mock API response to include it.
@@ -837,7 +853,7 @@ describe('Channel', () => {
837853
.fill(null)
838854
.map(() => generateMessage());
839855
await renderComponent(
840-
{ channel, chatClient },
856+
{ channel, channelQueryOptions: { messages: { limit: 25 } }, chatClient },
841857
({ hasMore, loadMore, messages: contextMessages }) => {
842858
if (!contextMessages.some((message) => message.id === newMessages[0].id)) {
843859
// Our new messages are not yet passed as part of channel context. Call loadMore and mock API response to include it.
@@ -859,12 +875,15 @@ describe('Channel', () => {
859875
const queryPromise = new Promise(() => {});
860876
let isLoadingMore = false;
861877

862-
await renderComponent({ channel, chatClient }, ({ loadingMore, loadMore }) => {
863-
// return a promise that hasn't resolved yet, so loadMore will be stuck in the 'await' part of the function
864-
jest.spyOn(channel, 'query').mockImplementationOnce(() => queryPromise);
865-
loadMore();
866-
isLoadingMore = loadingMore;
867-
});
878+
await renderComponent(
879+
{ channel, channelQueryOptions: { messages: { limit: 25 } }, chatClient },
880+
({ loadingMore, loadMore }) => {
881+
// return a promise that hasn't resolved yet, so loadMore will be stuck in the 'await' part of the function
882+
jest.spyOn(channel, 'query').mockImplementationOnce(() => queryPromise);
883+
loadMore();
884+
isLoadingMore = loadingMore;
885+
},
886+
);
868887
await waitFor(() => expect(isLoadingMore).toBe(true));
869888
});
870889

@@ -912,7 +931,7 @@ describe('Channel', () => {
912931
let queryNextPageSpy;
913932
let contextMessageCount;
914933
await renderComponent(
915-
{ channel, chatClient },
934+
{ channel, channelQueryOptions: { messages: { limit: 25 } }, chatClient },
916935
({ loadMore, messages: contextMessages }) => {
917936
queryNextPageSpy = jest.spyOn(channel, 'query');
918937
contextMessageCount = contextMessages.length;
@@ -935,9 +954,9 @@ describe('Channel', () => {
935954
expect(chatClient.axiosInstance.post.mock.calls[1][1]).toMatchObject(
936955
expect.objectContaining({
937956
data: {},
938-
messages: { id_lt: firstPageMessages[0].id, limit: 100 },
957+
messages: { id_lt: firstPageMessages[0].id, limit: 25 },
939958
state: true,
940-
watchers: { limit: 100 },
959+
watchers: { limit: 25 },
941960
}),
942961
);
943962
expect(contextMessageCount).toBe(

src/components/ChannelList/ChannelList.tsx

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import {
3131
useComponentContext,
3232
} from '../../context';
3333
import { NullComponent } from '../UtilityComponents';
34-
import { MAX_QUERY_CHANNELS_LIMIT, moveChannelUpwards } from './utils';
34+
import { moveChannelUpwards } from './utils';
3535
import type { CustomQueryChannelsFn } from './hooks/usePaginatedChannels';
3636
import type { ChannelListMessengerProps } from './ChannelListMessenger';
3737
import type { ChannelPreviewUIComponentProps } from '../ChannelPreview/ChannelPreview';
@@ -234,10 +234,7 @@ const UnMemoizedChannelList = (props: ChannelListProps) => {
234234
channels: Array<Channel>,
235235
setChannels: React.Dispatch<React.SetStateAction<Array<Channel>>>,
236236
) => {
237-
if (
238-
!channels.length ||
239-
channels.length > (options?.limit || MAX_QUERY_CHANNELS_LIMIT)
240-
) {
237+
if (!channels.length) {
241238
return;
242239
}
243240

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

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ describe('ChannelList', () => {
186186
const props = {
187187
filters: {},
188188
List: ChannelListComponent,
189+
options: { limit: 25, message_limit: 25 },
189190
Preview: ChannelPreviewComponent,
190191
};
191192

@@ -291,6 +292,7 @@ describe('ChannelList', () => {
291292
channelRenderFilterFn: customFilterFunction,
292293
filters: {},
293294
List: ChannelListComponent,
295+
options: { limit: 25, message_limit: 25 },
294296
Preview: ChannelPreviewComponent,
295297
};
296298

@@ -634,7 +636,13 @@ describe('ChannelList', () => {
634636
customActiveChannel={testChannel2.channel.id}
635637
filters={{}}
636638
List={ChannelListComponent}
637-
options={{ presence: true, state: true, watch: true }}
639+
options={{
640+
limit: 25,
641+
message_limit: 25,
642+
presence: true,
643+
state: true,
644+
watch: true,
645+
}}
638646
Preview={ChannelPreviewComponent}
639647
setActiveChannel={setActiveChannel}
640648
setActiveChannelOnMount
@@ -931,6 +939,7 @@ describe('ChannelList', () => {
931939
const channelListProps = {
932940
filters: {},
933941
List: ChannelListComponent,
942+
options: { limit: 25, message_limit: 25 },
934943
Preview: ChannelPreviewComponent,
935944
renderChannels,
936945
};
@@ -957,6 +966,7 @@ describe('ChannelList', () => {
957966
const props = {
958967
filters: {},
959968
List: ChannelListComponent,
969+
options: { limit: 25, message_limit: 25 },
960970
Preview: ChannelPreviewComponent,
961971
};
962972
const sendNewMessageOnChannel3 = async () => {
@@ -1065,7 +1075,13 @@ describe('ChannelList', () => {
10651075
<ChannelList
10661076
filters={{}}
10671077
List={ChannelListComponent}
1068-
options={{ presence: true, state: true, watch: true }}
1078+
options={{
1079+
limit: 25,
1080+
message_limit: 25,
1081+
presence: true,
1082+
state: true,
1083+
watch: true,
1084+
}}
10691085
Preview={ChannelPreviewComponent}
10701086
/>
10711087
</Chat>,
@@ -1104,7 +1120,13 @@ describe('ChannelList', () => {
11041120
filters={{}}
11051121
List={ChannelListComponent}
11061122
onMessageNew={onMessageNew}
1107-
options={{ presence: true, state: true, watch: true }}
1123+
options={{
1124+
limit: 25,
1125+
message_limit: 25,
1126+
presence: true,
1127+
state: true,
1128+
watch: true,
1129+
}}
11081130
Preview={ChannelPreviewComponent}
11091131
/>
11101132
</Chat>,
@@ -1131,7 +1153,13 @@ describe('ChannelList', () => {
11311153
const channelListProps = {
11321154
filters: {},
11331155
List: ChannelListComponent,
1134-
options: { presence: true, state: true, watch: true },
1156+
options: {
1157+
limit: 25,
1158+
message_limit: 25,
1159+
presence: true,
1160+
state: true,
1161+
watch: true,
1162+
},
11351163
Preview: ChannelPreviewComponent,
11361164
};
11371165

@@ -1200,6 +1228,7 @@ describe('ChannelList', () => {
12001228
const channelListProps = {
12011229
filters: {},
12021230
List: ChannelListComponent,
1231+
options: { limit: 25, message_limit: 25 },
12031232
Preview: ChannelPreviewComponent,
12041233
};
12051234

@@ -1263,6 +1292,7 @@ describe('ChannelList', () => {
12631292
const channelListProps = {
12641293
filters: {},
12651294
List: ChannelListComponent,
1295+
options: { limit: 25, message_limit: 25 },
12661296
Preview: ChannelPreviewComponent,
12671297
};
12681298

@@ -1331,6 +1361,7 @@ describe('ChannelList', () => {
13311361
const channelListProps = {
13321362
filters: {},
13331363
List: ChannelListComponent,
1364+
options: { limit: 25, message_limit: 25 },
13341365
Preview: ChannelPreviewComponent,
13351366
};
13361367

@@ -1420,6 +1451,7 @@ describe('ChannelList', () => {
14201451
const channelListProps = {
14211452
filters: {},
14221453
List: ChannelListComponent,
1454+
options: { limit: 25, message_limit: 25 },
14231455
Preview: ChannelPreviewComponent,
14241456
};
14251457

@@ -1487,7 +1519,13 @@ describe('ChannelList', () => {
14871519
const channelListProps = {
14881520
filters: {},
14891521
List: ChannelListComponent,
1490-
options: { presence: true, state: true, watch: true },
1522+
options: {
1523+
limit: 25,
1524+
message_limit: 25,
1525+
presence: true,
1526+
state: true,
1527+
watch: true,
1528+
},
14911529
Preview: ChannelPreviewComponent,
14921530
};
14931531

@@ -1555,6 +1593,7 @@ describe('ChannelList', () => {
15551593
const channelListProps = {
15561594
filters: {},
15571595
List: ChannelListComponent,
1596+
options: { limit: 25, message_limit: 25 },
15581597
Preview: ChannelPreviewComponent,
15591598
};
15601599

@@ -1595,6 +1634,7 @@ describe('ChannelList', () => {
15951634
const channelListProps = {
15961635
filters: {},
15971636
List: ChannelListComponent,
1637+
options: { limit: 25, message_limit: 25 },
15981638
Preview: ChannelPreviewComponent,
15991639
};
16001640

0 commit comments

Comments
 (0)