Overview
The client keeps everything you render in reactive state stores (updated from API calls, WebSocket events, etc.). This chapter shows where each kind of data lives and how to read it.
The model
-
State is a store you can subscribe to. Read the current value with
getLatestValue(). Subscribe to changes withsubscribe()/subscribeWithSelector(). -
Every list is a paginator. Messages, replies, pinned messages, channel and thread lists, and reminders share one API. See Pagination.
-
Each channel and thread is a singleton. Get its instance with
client.channel()orclient.threads.ensure(). -
Timestamps are nanosecond numbers. Convert them with
nsToDate(message.created_at).
Reading state
The same calls work on every store in this chapter.
// Read the current value
const { items } = channel.messagePaginator.state.getLatestValue();
// React to any change in the store
const unsubscribeChannel = channel.state.subscribe((state) =>
renderChannel(state),
);
// React to changes of selected values only.
// Return a small, flat object: it is compared key by key.
const unsubscribeHeader = channel.state.subscribeWithSelector(
({ typing, memberCount }) => ({ typing, memberCount }),
({ typing, memberCount }) => renderHeader(typing, memberCount),
);
// Stop listening
unsubscribeChannel();
unsubscribeHeader();In React, use useStateStore:
const { items } = useStateStore(channel.messagePaginator.state, (state) => ({
items: state.items,
}));Pagination
Lists have paginator state that works this way:
A paginator's state holds the loaded items, isLoading, hasMoreHead, hasMoreTail and lastQueryError. items is undefined until the first page loads.
const paginator = channel.messagePaginator;
const { items, isLoading, hasMoreTail, lastQueryError } =
paginator.state.getLatestValue();
// Load the next page
if (paginator.hasMoreTail) {
await paginator.toTail();
}
// Load the first page again
await paginator.reload();toTail() loads the next page toward the end of the list: older messages in a message list, and the next channels, threads or reminders in the others. toHead() loads toward the start. You only need it in a message list after jumping to a message, to load the newer messages.
A failed page doesn't throw. The error is in lastQueryError, and calling toTail() again retries.
To change what a list loads, such as its filters, sort or page size, see the "Configure the query" section of its page.
v9 vs v10
See how the most important concepts compare in v9 and v10:
| v9 | v10 |
|---|---|
channel.state.messages |
channel.messagePaginator.state → items |
channel.state.pinnedMessages |
channel.pinnedMessagesPaginator.state → items |
thread.state.replies |
thread.messagePaginator.state → items |
channelManager.state.channels |
channelPaginator.state → items |
threadManager.state.threads |
client.threads.paginator.state → items |
client.configs[cid] |
channel.serverConfig |
connection.changed event |
client.wsConnection.state → isHealthy |
created_at as a Date |
nanosecond number, convert with nsToDate() |