# Loading data hooks

> **Info:** This is release candidate documentation for **Stream Chat React Native SDK v10**. For the latest stable version, see the [latest version (v9)](https://getstream.io/chat/docs/sdk/react-native/).

These hooks read channel lists, message lists, the thread list and the reminder list. The paginators behind them are explained under State > Loading data: [How pagination works](https://getstream.io/chat/docs/sdk/react-native/v10/state/loading-data/how-pagination-works/), [Channel list paginators](https://getstream.io/chat/docs/sdk/react-native/v10/state/loading-data/channel-list-paginators/) and [Message paginators](https://getstream.io/chat/docs/sdk/react-native/v10/state/loading-data/message-paginators/). How to read state in components is on [Reading state in components](https://getstream.io/chat/docs/sdk/react-native/v10/ui/reading-state-in-components/).

Each entry gives the signature, then:

- **Returns:** what the hook gives back.
- **Reads:** the store or the context it reads.
- **Re-renders:** what makes the component render again.
- **Needs:** where the component must sit, and what the hook does outside that place.

## useChannelsContext

Returns the paginator and the settings of the `ChannelList` around the component.

```ts
useChannelsContext(): ChannelsContextValue
```

- **Returns:**
  - `paginator`: the `ChannelPaginator` passed to `ChannelList`.
  - `loadNextPage()`: loads the next page, with `ChannelPaginator.toTail()`. It does nothing until the first page has loaded.
  - `reloadList()`: clears the list and loads the first page again. The list shows its loading state meanwhile.
  - `refreshList()`: loads the first page again and keeps the channels on screen meanwhile, as pull to refresh does. A call within 5 seconds of the previous one, or of the list mounting, is ignored, unless the last query failed.
  - `onSelect`, `getChannelActionItems`, `swipeActionsEnabled`, `additionalFlatListProps`, `setFlatListRef`, `loadMoreThreshold`, `maxUnreadCount`, `numberOfSkeletons`, `mutedStatusPosition` and `pinnedStatusPosition`: the `ChannelList` props of the same names, with their defaults applied.
- **Reads:** the context `ChannelList` provides. No store.
- **Re-renders:** when `ChannelList` provides a new value, which happens when one of its props changes. Not when the channels change: read those from `paginator.state` with `useStateStore`.
- **Needs:** `ChannelList`. Throws outside it.

The props are on [ChannelsContext](https://getstream.io/chat/docs/sdk/react-native/v10/component-reference/channel-list/channelscontext/).

### The channels of a list

No hook returns the channels. Read them from the paginator's `state`, which holds `items` (`undefined` until the first page loads), `isLoading`, `hasMoreTail`, `hasMoreHead` and `lastQueryError`. A footer for your own `ChannelList` component reads it like this:

```tsx
import { Pressable, Text } from "react-native";
import type { ChannelPaginatorState } from "stream-chat";
import { useChannelsContext, useStateStore } from "stream-chat-react-native";

const footerSelector = (state: ChannelPaginatorState) => ({
  hasMoreTail: state.hasMoreTail,
  isLoading: state.isLoading,
  items: state.items,
  lastQueryError: state.lastQueryError,
});

export const ChannelListFooter = () => {
  const { loadNextPage, paginator, reloadList } = useChannelsContext();
  const { hasMoreTail, isLoading, items, lastQueryError } = useStateStore(
    paginator.state,
    footerSelector,
  );

  if (lastQueryError) {
    return (
      <Pressable accessibilityRole="button" onPress={() => reloadList()}>
        <Text>Couldn't load channels. Retry</Text>
      </Pressable>
    );
  }
  if (!hasMoreTail) return <Text>{items?.length ?? 0} channels</Text>;

  return (
    <Pressable
      accessibilityRole="button"
      disabled={isLoading}
      onPress={() => loadNextPage()}
    >
      <Text>Load more</Text>
    </Pressable>
  );
};
```

Outside a `ChannelList`, read the same store on the paginator you created. The paginator's fields are on [Channel manager and ChannelPaginator](https://getstream.io/chat/docs/sdk/react-native/v10/reference/state/channel-manager-and-channelpaginator/).

## useMessagePaginator

Returns the message list of the channel or the thread the component renders in.

```ts
useMessagePaginator(): MessagePaginator
```

- **Returns:** `thread.messagePaginator` inside a `Thread`, otherwise `channel.messagePaginator` of the `Channel`. It's the list `MessageList` and `MessageFlashList` render.
- **Reads:** the `Thread` and `Channel` contexts. No store.
- **Re-renders:** when the thread or the channel in context changes. Not when the messages change: read those from `paginator.state` with `useStateStore`.
- **Needs:** a `Channel` or a `Thread`. Throws outside both.

```tsx
import { Text } from "react-native";
import type { MessagePaginatorState } from "stream-chat";
import { useMessagePaginator, useStateStore } from "stream-chat-react-native";

const itemsSelector = (state: MessagePaginatorState) => ({
  items: state.items,
});

export const LoadedMessageCount = () => {
  const paginator = useMessagePaginator();
  const { items } = useStateStore(paginator.state, itemsSelector);

  return <Text>{items?.length ?? 0} messages loaded</Text>;
};
```

A message paginator's `state` publishes at most once every 500 ms by default, as [Batched message-list updates](https://getstream.io/chat/docs/sdk/react-native/v10/ui/reading-state-in-components/#batched-message-list-updates) explains. Its other stores, `unreadStateSnapshot`, `liveViewState`, `aggregateState` and `messageFocusSignal`, publish at once. The fields of a message list are on [Message paginator](https://getstream.io/chat/docs/sdk/react-native/v10/reference/state/message-paginator/), and how it loads on [Message paginators](https://getstream.io/chat/docs/sdk/react-native/v10/state/loading-data/message-paginators/).

## useIsTargetedMessage

Says whether a message is the one the list jumped to.

```ts
useIsTargetedMessage(messageId: string): boolean
```

- **Returns:** `true` while the message is the target of the paginator's focus signal. `MessagePaginator.jumpToMessage()` and `MessagePaginator.jumpToTheFirstUnreadMessage()` set the signal, and it clears itself after a short time.
- **Reads:** `messageFocusSignal` of the paginator from `useMessagePaginator()`, its `signal.messageId`.
- **Re-renders:** when the message becomes the target, and when it stops being it. A jump re-renders the row that loses the highlight and the row that gains it, not every row.
- **Needs:** a `Channel` or a `Thread`. Throws outside both.

The default message highlights itself with it. Jumping to a message is explained on [Moving between channels, threads and messages](https://getstream.io/chat/docs/sdk/react-native/v10/ui/layout/moving-between-channels-threads-and-messages/#jumping-to-a-message).

## useThreadsContext

Returns the threads and the settings of the `ThreadList` around the component.

```ts
useThreadsContext(): ThreadsContextValue
```

- **Returns:**
  - `threads`: the loaded threads, from `client.threads.paginator.state`.
  - `isLoading`: `true` while a page loads and no thread is loaded yet. `isLoadingNext`: `true` while a page loads and threads are already shown.
  - `loadMore()`: loads the next page, with `client.threads.paginator.toTail()`.
  - `isFocused`, `onThreadSelect` and `additionalFlatListProps`: the `ThreadList` props of the same names. `isFocused` is `undefined` when the prop isn't passed, although `ThreadList` treats a missing prop as `true`.
- **Reads:** the context `ThreadList` provides. `ThreadList` subscribes to `client.threads.paginator.state` and passes the result down.
- **Re-renders:** whenever `ThreadList` renders, since it passes a new value each time. That includes every change to the thread list's loading state and items.
- **Needs:** `ThreadList`. Throws outside it.

`ThreadList` also calls `client.threads.activate()` while `isFocused` is `true`, and `client.threads.deactivate()` when it becomes `false` and when the list unmounts. Activating the thread manager loads the first page when the list has none, and reloads it when threads got replies while it was inactive. `ThreadListProps` types `isFocused` as required, although it defaults to `true`. Pass the focus state of the screen, as [Thread UI](https://getstream.io/chat/docs/sdk/react-native/v10/ui/components/thread-ui/#the-thread-list) shows.

A thread list of your own, without `ThreadList`, reads `client.threads.paginator.state` with `useStateStore` and activates `client.threads` itself. `Chat` starts the thread manager's event handling, so render it inside `Chat`:

```tsx
import { useEffect } from "react";
import { FlatList, Pressable, Text } from "react-native";
import type { PaginatorState, Thread, ThreadState } from "stream-chat";
import { useChatContext, useStateStore } from "stream-chat-react-native";

const threadsSelector = (state: PaginatorState<Thread>) => ({
  isLoading: state.isLoading,
  threads: state.items,
});

const titleSelector = (state: ThreadState) => ({ title: state.title });

const ThreadRow = ({
  onPress,
  thread,
}: {
  onPress: (thread: Thread) => void;
  thread: Thread;
}) => {
  const { title } = useStateStore(thread.state, titleSelector);

  return (
    <Pressable accessibilityRole="button" onPress={() => onPress(thread)}>
      <Text>{title}</Text>
    </Pressable>
  );
};

export const CompactThreadList = ({
  onThreadPress,
}: {
  onThreadPress: (thread: Thread) => void;
}) => {
  const { client } = useChatContext();
  const { isLoading, threads } = useStateStore(
    client.threads.paginator.state,
    threadsSelector,
  );

  useEffect(() => {
    client.threads.activate();
    return () => client.threads.deactivate();
  }, [client]);

  if (isLoading && !threads?.length) return <Text>Loading threads...</Text>;

  return (
    <FlatList
      data={threads ?? []}
      keyExtractor={(thread) => thread.id}
      onEndReached={() => client.threads.paginator.toTail()}
      renderItem={({ item }) => (
        <ThreadRow onPress={onThreadPress} thread={item} />
      )}
    />
  );
};
```

The thread list is explained on [Replies and threads](https://getstream.io/chat/docs/sdk/react-native/v10/features/messaging/replies-and-threads/#the-thread-list), and its API on [Thread and thread manager](https://getstream.io/chat/docs/sdk/react-native/v10/reference/state/thread-and-thread-manager/).

## useQueryReminders

Returns the reminder list, kept in step with reminder events.

```ts
useQueryReminders(): {
  data: ReminderResponseData[];
  isLoading: boolean;
  loadNext: () => Promise<void>;
  setData: Dispatch<SetStateAction<ReminderResponseData[]>>;
}
```

It reads `client.reminders.paginator.state`, and doesn't load a page by itself. The full entry is on [Reminder hooks](https://getstream.io/chat/docs/sdk/react-native/v10/reference/hooks/reminder-hooks/#usequeryreminders).

## Lists without a hook

Read these lists with `useStateStore` and your own selector:

| List                      | Store                                                                                                                                                                          |
| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| A channel list            | `paginator.state` of the paginator you pass to `ChannelList`                                                                                                                   |
| The thread list           | `client.threads.paginator.state`                                                                                                                                               |
| A thread's replies        | `thread.messagePaginator.state`                                                                                                                                                |
| The channel details lists | `searchSource.state` of each list's context. See [Channel details hooks](https://getstream.io/chat/docs/sdk/react-native/v10/reference/hooks/channel-details-hooks/#the-lists-of-channel-details). |

---

For the most recent version of this documentation, visit [https://getstream.io/chat/docs/sdk/react-native/v10/reference/hooks/loading-data-hooks/](https://getstream.io/chat/docs/sdk/react-native/v10/reference/hooks/loading-data-hooks/).