Skip to main content

Bottom Sheet in React Native

· 5 min read
Full Stack Developer
Last updated on May 17, 2026

react-native-bottom-sheet

A bottom sheet is a mobile surface that slides up from the bottom of the screen. It is useful for filters, sorting controls, checkout options, map place details, share menus, comments, media actions, and short forms.

React Native bottom sheets are gesture-heavy. A production implementation needs more than a visible prop: it needs Gesture Handler, Reanimated, stable snap points, keyboard behavior, safe areas, scrollable content, and cleanup around navigation.

Quick Answer

For most React Native apps, use @gorhom/bottom-sheet. Install it with the gesture and animation dependencies expected by your app, wrap the app with GestureHandlerRootView, and use refs to present or control the sheet.

corepack yarn add @gorhom/bottom-sheet
corepack yarn expo install react-native-reanimated react-native-gesture-handler

If your app already includes Reanimated and Gesture Handler, do not upgrade them blindly. Check the current React Native stack, your app lockfile, and the package documentation first.

Install and Rebuild

Bottom sheets rely on native gesture and animation libraries. After installing or changing those libraries, rebuild the native app:

corepack yarn ios
corepack yarn android

For iOS native dependency issues, use iOS and CocoaPods Errors. For Android build issues, use Android and Gradle Errors.

Add Gesture Handler at the Root

Gesture Handler needs a root view close to the top of the app:

import { GestureHandlerRootView } from 'react-native-gesture-handler';
import RootNavigator from './src/navigation/RootNavigator';

export default function App() {
return (
<GestureHandlerRootView style={{ flex: 1 }}>
<RootNavigator />
</GestureHandlerRootView>
);
}

If you render bottom sheets inside native modals or separate roots, those roots may need their own GestureHandlerRootView.

Mega Bundle Sale is ON! Get ALL of our React Native codebases at 90% OFF discount 🔥

Get the Mega Bundle

Create a Basic Bottom Sheet

Use BottomSheet for a sheet that is always mounted on a screen:

import { useMemo, useRef } from 'react';
import { StyleSheet, Text } from 'react-native';
import BottomSheet, { BottomSheetView } from '@gorhom/bottom-sheet';

export function ProductOptionsSheet() {
const sheetRef = useRef<BottomSheet>(null);
const snapPoints = useMemo(() => ['25%', '55%'], []);

return (
<BottomSheet ref={sheetRef} index={0} snapPoints={snapPoints}>
<BottomSheetView style={styles.content}>
<Text style={styles.title}>Product options</Text>
</BottomSheetView>
</BottomSheet>
);
}

const styles = StyleSheet.create({
content: {
padding: 20,
},
title: {
fontSize: 18,
fontWeight: '700',
},
});

Keep snap points memoized so the sheet does not recalculate them on every render.

Use Bottom Sheet Modal for Actions

Use BottomSheetModal when the sheet opens in response to a button press or navigation action:

import { useCallback, useMemo, useRef } from 'react';
import { Button, Text } from 'react-native';
import {
BottomSheetModal,
BottomSheetModalProvider,
BottomSheetView,
} from '@gorhom/bottom-sheet';

export function FilterSheetExample() {
const modalRef = useRef<BottomSheetModal>(null);
const snapPoints = useMemo(() => ['40%', '80%'], []);

const openFilters = useCallback(() => {
modalRef.current?.present();
}, []);

return (
<BottomSheetModalProvider>
<Button title="Open filters" onPress={openFilters} />
<BottomSheetModal ref={modalRef} snapPoints={snapPoints}>
<BottomSheetView style={{ padding: 20 }}>
<Text>Filters</Text>
</BottomSheetView>
</BottomSheetModal>
</BottomSheetModalProvider>
);
}

Place the provider high enough that screens needing modal sheets can access it.

Use the Built-In Scrollables

Bottom sheets need gesture coordination between the sheet and the content inside it. Prefer the package scrollables:

import BottomSheet, { BottomSheetFlatList } from '@gorhom/bottom-sheet';

export function CommentsSheet({ comments }: { comments: Comment[] }) {
return (
<BottomSheet snapPoints={['45%', '90%']}>
<BottomSheetFlatList
data={comments}
keyExtractor={(item) => item.id}
renderItem={({ item }) => <CommentRow comment={item} />}
/>
</BottomSheet>
);
}

For search inputs or message composers inside a sheet, use the package's keyboard-aware components and test on both iOS and Android.

Design and Accessibility Checklist

Bottom sheets work best when they have a clear job:

  • use two or three snap points, not a long list;
  • keep destructive actions visually separated;
  • avoid nesting full navigation flows inside a sheet;
  • respect safe areas and keyboard movement;
  • provide a visible close action for modal sheets;
  • keep forms short enough to complete comfortably;
  • test with screen reader focus if the sheet contains important controls.

For device behavior such as safe areas, review Avoid Notch and Safe Area Issues in React Native.

Troubleshooting

If the sheet does not drag, check:

  • GestureHandlerRootView wraps the app;
  • Reanimated and Gesture Handler versions match the app;
  • native apps were rebuilt after installation;
  • the Reanimated/Worklets Babel plugin setup matches your app;
  • scrollable content uses bottom-sheet scrollables;
  • modals have a gesture root when required.

If Metro or native builds fail after dependency changes, start with React Native Errors and Solutions.

Looking for a custom mobile application?

Our team of expert mobile developers can help you build a custom mobile app that meets your specific needs.

Get in Touch

FAQ

Should I use a custom bottom sheet or a library?

Use a library for production sheets with gestures, scrollables, keyboard handling, and accessibility. A custom sheet is reasonable only for a simple non-interactive panel.

Why does my bottom sheet not respond to gestures?

The most common cause is missing GestureHandlerRootView or mismatched native dependencies. Rebuild the app after changing gesture or animation packages.

Can I put a FlatList inside a bottom sheet?

Yes, but use the bottom-sheet package's scrollable components so the sheet and list gestures coordinate correctly.