# ScrollToBottomButton

> **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/).

`ScrollToBottomButton` is the round button that floats over the bottom of the message list while the user isn't at the latest message. In a channel, its badge shows the user's unread count. `MessageList` and `MessageFlashList` render it through the `ScrollToBottomButton` override key and pass it what a press does. [Floating controls](https://getstream.io/chat/docs/sdk/react-native/v10/ui/components/message-list-ui/#floating-controls) explains when it shows.

## Best practices

- Replace it with the `ScrollToBottomButton` override key, and call the `onPress` the list passes. The list decides what a press does: scroll down, or jump to the latest messages when they aren't loaded, then mark the channel read.
- Return `null` when `showNotification` is `false`. `MessageFlashList` keeps the button mounted and passes `false` while it should be hidden.
- Read the unread count from the channel's read state, as the default does, rather than counting messages yourself.

## Basic usage

This replacement shows a text button with the unread count:

```tsx title="src/JumpToLatestButton.tsx"
import { Pressable, StyleSheet, Text } from "react-native";
import type { ReadState } from "stream-chat";
import {
  type ScrollToBottomButtonProps,
  useChannel,
  useChatContext,
  useStateStore,
  useThreadContext,
  WithComponents,
} from "stream-chat-react-native";

const selectRead = (state: ReadState) => ({ read: state.read });

const JumpToLatestButton = ({
  onPress,
  showNotification = true,
}: ScrollToBottomButtonProps) => {
  const { client } = useChatContext();
  const channel = useChannel();
  const { thread } = useThreadContext();
  const { read } = useStateStore(channel.state, selectRead);
  const unreadCount = client.userId
    ? (read[client.userId]?.unread_messages ?? 0)
    : 0;

  if (!showNotification) {
    return null;
  }

  return (
    <Pressable
      accessibilityRole="button"
      onPress={onPress}
      style={styles.button}
    >
      <Text style={styles.label}>
        {!thread && unreadCount ? `${unreadCount} new` : "Latest"}
      </Text>
    </Pressable>
  );
};

const overrides = { ScrollToBottomButton: JumpToLatestButton };

export const ListWithJumpButton = ({
  children,
}: {
  children: React.ReactNode;
}) => <WithComponents overrides={overrides}>{children}</WithComponents>;

const styles = StyleSheet.create({
  button: {
    backgroundColor: "#005fff",
    borderRadius: 16,
    paddingHorizontal: 12,
    paddingVertical: 6,
  },
  label: { color: "white", fontWeight: "600" },
});
```

The list positions the button absolutely, 16 points from the right, and above the composer when the composer floats. Change the position through `theme.messageList.scrollToBottomButtonContainer`.

## What the default renders

- An outlined icon button with the `Down` icon from the `icons` override map.
- In a channel, a badge with the user's unread count, from `channel.state`'s read state, while the count is above zero. In a thread, no badge.
- Its accessibility label is `messageList.scrollToBottom.accessibilityLabel`, or `messageList.scrollToBottom.withCount.accessibilityLabel` with the count. The keys are exported as `SCROLL_TO_BOTTOM_ACCESSIBILITY_LABEL_KEY` and `SCROLL_TO_BOTTOM_WITH_COUNT_ACCESSIBILITY_LABEL_KEY`.

With [accessibility](https://getstream.io/chat/docs/sdk/react-native/v10/features/app-experience/accessibility/) turned on, the list also gets a scroll-to-bottom accessibility action while the button shows, so screen reader users reach the same jump without finding the button.

## Props

| Prop               | Type         | Default  | Description                                                                                                                                                                                                                                                                                                    |
| ------------------ | ------------ | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `onPress`          | `() => void` | required | Called when the user presses the button. The list passes a function that scrolls to the newest message, or jumps to the latest messages when they aren't loaded, hides the button, and in a channel marks the channel read with `updateChannelUnreadState: false`, so the unread separator stays where it was. |
| `showNotification` | `boolean`    | `true`   | Whether the button renders. `MessageList` mounts the button only while it should show; `MessageFlashList` mounts it always and passes the visibility here.                                                                                                                                                     |

## Related hooks

- `useChannel()` and `useThreadContext()` tell the button whether it's in a thread.
- `useStateStore(channel.state, selector)` reads the channel's read state, as in the sample above.
- `useMessagePaginator()` returns the paginator the list renders. Its `hasMoreHead` is `true` while the latest messages aren't loaded, and `MessagePaginator.jumpToTheLatestMessage()` loads them. See [Message paginator](https://getstream.io/chat/docs/sdk/react-native/v10/reference/state/message-paginator/).

---

For the most recent version of this documentation, visit [https://getstream.io/chat/docs/sdk/react-native/v10/component-reference/message-list/scroll-to-bottom-button/](https://getstream.io/chat/docs/sdk/react-native/v10/component-reference/message-list/scroll-to-bottom-button/).