# List states UI

The SDK's lists show a state of their own while they load, when a load fails, and when they're empty. Use this page to know which states each list has, which ones you can replace, and what happens when a first page fails to load.

## States and their keys

Each cell names the `<WithComponents/>` key that replaces the state. "Built in" means the list renders a fixed component that no key replaces. "None" means the list has no such state. To register a replacement, see [How WithComponents overrides work](https://getstream.io/chat/docs/sdk/react/ui/components/overriding-components/#how-withcomponents-overrides-work). [ComponentContext](https://getstream.io/chat/docs/sdk/react/component-reference/channel/componentcontext/) lists each key's default.

| List                                  | First page loading                              | First page failed                           | Next page loading                              | Empty                                  | Start or end reached                        |
| ------------------------------------- | ----------------------------------------------- | ------------------------------------------- | ---------------------------------------------- | -------------------------------------- | ------------------------------------------- |
| `<ChannelList/>`                      | `FirstPageLoadingIndicator`                     | `ListLoadErrorIndicator`                    | `LoadingNextPageIndicator`                     | `EmptyListIndicator`                   | `EndReachedIndicator`                       |
| `<ThreadList/>`                       | `FirstPageLoadingIndicator`                     | `ListLoadErrorIndicator`                    | `ThreadListLoadingIndicator`                   | `ThreadListEmptyPlaceholder`           | None                                        |
| `<MessageList/>`                      | None                                            | None                                        | `LoadingIndicator`, older pages only           | `EmptyStateIndicator`, not in a thread | None                                        |
| `<VirtualizedMessageList/>`           | None                                            | None                                        | `LoadingIndicator`, at the top, for every page | `EmptyStateIndicator`                  | None                                        |
| `<SearchSourceResults/>`, per source  | `SearchSourceResultsLoadingIndicator`           | None                                        | `SearchSourceResultsLoadingIndicator`          | `SearchSourceResultsEmpty`             | Built in, in `SearchSourceResultListFooter` |
| `<MessageReactionsDetail/>` user list | `LoadingIndicator`, until every page has loaded | None                                        | None                                           | None                                   | None                                        |
| `<PollAnswerList/>`                   | Built in                                        | Built in: the error's message, for any page | Built in                                       | None                                   | None                                        |
| `<PollOptionWithVotesList/>`          | Built in                                        | None                                        | Built in                                       | None                                   | None                                        |
| `<ChannelDetail/>` views              | Built in                                        | None                                        | Built in                                       | Built in                               | None                                        |
| `<SuggestionList/>` in the composer   | None                                            | None                                        | None                                           | None                                   | None                                        |

Neither message list has first-page states. `<Channel/>` takes a channel that is already loaded and doesn't query it. `<Thread/>` loads a stale thread's replies itself, and the message list shows the parent message meanwhile, without a loading or error view.

`<MessageReactionsDetail/>` loads up to 1,000 reactions, 25 at a time, before it shows the list. A failed load leaves the list empty and publishes an error notification.

The `SearchSourceResultListFooter` key replaces both the next-page and the end-of-list state of search results. `<PollActions/>` takes a `PollAnswerList` prop that replaces the whole answer list.

`<SuggestionList/>`, the composer's mentions, commands and emoji, loads more suggestions as the user scrolls. It shows only while it has suggestions, so it has none of these states.

The `<ChannelDetail/>` views, from `stream-chat-react/channel-detail`, list the members, the users to add as members, media, files and pinned messages. [Channel details UI](https://getstream.io/chat/docs/sdk/react/ui/components/channel-details-ui/) shows the panel.

`ListLoadErrorIndicator` gets [`ListLoadErrorIndicatorProps`](https://getstream.io/chat/docs/sdk/react/component-reference/utilities/indicators/#listloaderrorindicatorprops). `LoadingNextPageIndicator` gets `isLoading`, and `EndReachedIndicator` gets `hasEnded` and `reached` (`"top"` or `"bottom"`). The props of `EmptyStateIndicator` and `LoadingIndicator` are in [Indicators](https://getstream.io/chat/docs/sdk/react/component-reference/utilities/indicators/). The other keys take no props.

## When the first page fails

Only `<ChannelList/>` and `<ThreadList/>` have an error view you can replace and retry:

1. The query fails, after the paginator's retries. The list keeps showing `FirstPageLoadingIndicator` meanwhile.
2. The paginator records the error as `lastQueryError` in its state. The list renders `ListLoadErrorIndicator` in place of its rows.
3. The list publishes an error notification.
4. The list waits for a new query.

|                               | `<ChannelList/>`                                                                        | `<ThreadList/>`                                                                                      |
| ----------------------------- | --------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
| Retries before the error      | Three, by default                                                                       | None, by default                                                                                     |
| Where the error is stored     | `state.lastQueryError` of the `ChannelPaginator` passed as the list's `paginator` prop  | `state.lastQueryError` of `client.threads.paginator`                                                 |
| Try again calls               | `ChannelPaginator.reload()`                                                             | `ThreadManager.reload({ force: true })` on `client.threads`                                          |
| Error notification            | `api:channel:query:failed` in the `channel-list` panel, shown by `<ChannelNavigation/>` | `api:thread:query:failed` in the `thread-list` panel, shown by `<ThreadList/>`                       |
| Other events that query again | A reset of the paginator, and connection recovery after a reconnect                     | Mounting the list again, the browser tab becoming visible, and connection recovery after a reconnect |

[FirstPageLoadingIndicator and ListLoadErrorIndicator](https://getstream.io/chat/docs/sdk/react/component-reference/utilities/indicators/#firstpageloadingindicator-and-listloaderrorindicator) explains the error view's focus handling and its translation key.

### During the new query

| What starts the query                   | What the list shows meanwhile                   |
| --------------------------------------- | ----------------------------------------------- |
| Try again                               | The error view, with `isRetrying` set to `true` |
| A reset of the channel list's paginator | `FirstPageLoadingIndicator`                     |
| Any event of the thread list            | `FirstPageLoadingIndicator`                     |
| The channel list's connection recovery  | The error view, with `isRetrying` left `false`  |

A reload of a loaded list differs between the two lists. `ChannelPaginator.reload()` clears the rows, so `FirstPageLoadingIndicator` shows until the new page arrives. `ThreadManager.reload()` on `client.threads` keeps the loaded threads until the new ones arrive.

### The error notification

- A query that fails after a page loaded, such as the next page or a reconnect recovery, keeps the loaded rows and only publishes the notification.
- With offline support on and channels loaded, a failed channel query publishes no notification.
- A `<ChannelList/>` rendered without `<ChannelNavigation/>` shows the error view but not the notification. [Showing it somewhere else](https://getstream.io/chat/docs/sdk/react/ui/components/notifications-ui/#showing-it-somewhere-else) shows how to render it.

## Replacing a state in one list only

`<ChannelList/>` and `<ThreadList/>` both read `FirstPageLoadingIndicator` and `ListLoadErrorIndicator`, so a replacement registered around both lists replaces them in both lists. `<MessageList/>` and `<VirtualizedMessageList/>` share `EmptyStateIndicator` the same way. `LoadingIndicator` reaches further: the default `ThreadListLoadingIndicator`, the reactions detail, upload previews and the video player read it too. To replace a state in one list, register it in a `<WithComponents/>` around that list only:

| Where the list renders                        | Wrap                                                                                                                                                                                                          |
| --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| The channel list under `<ChatView/>`'s layout | [`slotRenderers.channelList`](https://getstream.io/chat/docs/sdk/react/component-reference/layout/slot-layout/#slotrenderers), which renders `<ChannelNavigation/>` by default                                                    |
| The thread list under `<ChatView/>`'s layout  | [`slotRenderers.threadList`](https://getstream.io/chat/docs/sdk/react/component-reference/layout/slot-layout/#slotrenderers), which renders `<ThreadList/>` by default                                                            |
| A view you render yourself                    | The list it renders. [Replace the thread list's load error](https://getstream.io/chat/docs/sdk/react/component-reference/utilities/indicators/#replace-the-thread-lists-load-error) shows a replacement for the thread list only. |

The [Empty and loading states](https://getstream.io/chat/docs/sdk/react/ui-cookbooks/channel-list/empty-and-loading-states/) recipe replaces the channel list's first-page loading, error and empty states.

---

For the most recent version of this documentation, visit [https://getstream.io/chat/docs/sdk/react/ui/components/list-states-ui/](https://getstream.io/chat/docs/sdk/react/ui/components/list-states-ui/).