DEV Community

Cover image for How to Create a Bottom Sheet in React Native
Francisco Mendes
Francisco Mendes

Posted on

How to Create a Bottom Sheet in React Native

Overview

Nowadays we have a great diversity of components that are always necessary to create a web page or a mobile application and I believe that in almost all the applications we always end up having a Bottom Sheet.

This component has several use cases, from filling in forms, to performing an action such as creating, editing or deleting. However, it can also be used to show something in detail or when you want to introduce something on a screen but have no context for it, such as sending feedback or contacting support.

Now comes a dilemma, there are several ways to implement it, the same way that you can do everything by yourself, you can also use a dependency. I think that doing everything by hand, apart from taking much longer to implement, can also cause other problems. And on the other hand, sometimes when using a dependency we are stuck with certain limitations, the most famous ones are its stylization.

So in this example we will use two dependencies, one will be to create a portal (a very famous approach when working with modals) and the other will be a dependency to create hugely customizable modals.

Let's code

Let's install the following dependencies:

npm install @gorhom/portal react-native-modalize react-native-gesture-handler
Enter fullscreen mode Exit fullscreen mode

First let's create our component, which in this case will be the Bottom Sheet:

// @src/components/BottomSheet.jsx
import React from "react";

const BottomSheet = () => {
  // ...
};

export default BottomSheet;
Enter fullscreen mode Exit fullscreen mode

Now let's import the Portal and Modalize into our component:

// @src/components/BottomSheet.jsx
import React from "react";
import { Portal } from "@gorhom/portal";
import { Modalize } from "react-native-modalize";

const BottomSheet = () => {
  return (
    <Portal>
      <Modalize>
        // ...
      </Modalize>
    </Portal>
  );
};

export default BottomSheet;
Enter fullscreen mode Exit fullscreen mode

Then we will need to pass two attributes to our Modalize, the first will be the ref (which we will receive through the component's props) and the second will be the height of the modal.

To define the height of the modal we will import the Dimensions from React Native and we will create a variable called modalHeight which will be half the height of the screen.

// @src/components/BottomSheet.jsx
import React from "react";
import { Dimensions } from "react-native";
import { Portal } from "@gorhom/portal";
import { Modalize } from "react-native-modalize";

const { height } = Dimensions.get("screen");
const modalHeight = height * 0.5;

const BottomSheet = ({ modalRef }) => {
  return (
    <Portal>
      <Modalize ref={modalRef} modalHeight={modalHeight}>
        // ...
      </Modalize>
    </Portal>
  );
};

export default BottomSheet;
Enter fullscreen mode Exit fullscreen mode

After that we will start working on the content that we will have on the Bottom Sheet, in this case we will use a View as a wrapper of our content, then we will use a Text to have a small message and finally we will have a Button to close the Bottom Sheet.

To close the modal we will use a function that will be passed as the component's prop.

// @src/components/BottomSheet.jsx
import React from "react";
import { Dimensions, View, StyleSheet, Text, Button } from "react-native";
import { Portal } from "@gorhom/portal";
import { Modalize } from "react-native-modalize";

const { height } = Dimensions.get("screen");
const modalHeight = height * 0.5;

const BottomSheet = ({ modalRef, onClose }) => {
  return (
    <Portal>
      <Modalize ref={modalRef} modalHeight={modalHeight}>
        <View style={styles.content}>
          <Text style={styles.text}>Hello World</Text>
          <Button title="Close Modal" color="#F0F5F9" onPress={onClose} />
        </View>
      </Modalize>
    </Portal>
  );
};

export default BottomSheet;

const styles = StyleSheet.create({
  content: {
    flex: 1,
    justifyContent: "space-between",
    height: modalHeight,
    paddingHorizontal: 20,
    paddingVertical: 32,
    backgroundColor: "#52616B",
  },
  text: {
    fontSize: 48,
    fontWeight: "600",
    letterSpacing: 48 * 0.02,
    alignSelf: "center",
    color: "#C9D6DF",
  },
});
Enter fullscreen mode Exit fullscreen mode

Now on our App.js let's start by importing the PortalProvider which will be the root component of our application. Then we will import from React the useRef hook.

// @src/App.js
import React, { useRef } from "react";
import { PortalProvider } from "@gorhom/portal";

const App = () => {
  return (
    <PortalProvider>
      // ...
    </PortalProvider>
  );
};

export default App;
Enter fullscreen mode Exit fullscreen mode

First let's create our modalRef and we'll create two functions, one to open the modal and the other to close it.

// @src/App.js
import React, { useRef } from "react";
import { PortalProvider } from "@gorhom/portal";

const App = () => {
  const modalRef = useRef(null);

  const onOpen = () => {
    modalRef.current?.open();
  };

  const onClose = () => {
    modalRef.current?.close();
  };

  return (
    <PortalProvider>
      // ...
    </PortalProvider>
  );
};

export default App;
Enter fullscreen mode Exit fullscreen mode

Now we can import our Bottom Sheet component and we can pass it the necessary props. But before that, let's import from React Native the View component that will be the wrapper of the screen content and the Button that will be responsible for opening the BottomSheet.

// @src/App.js
import React, { useRef } from "react";
import { StyleSheet, Button, View } from "react-native";
import { PortalProvider } from "@gorhom/portal";

import BottomSheet from "./components/BottomSheet";

const App = () => {
  const modalRef = useRef(null);

  const onOpen = () => {
    modalRef.current?.open();
  };

  const onClose = () => {
    modalRef.current?.close();
  };

  return (
    <PortalProvider>
      <View style={styles.container}>
        <BottomSheet modalRef={modalRef} onClose={onClose} />
        <Button title="Open Modal" color="#1E2022" onPress={onOpen} />
      </View>
    </PortalProvider>
  );
};

export default App;

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#C9D6DF",
    alignItems: "center",
    justifyContent: "center",
  },
});
Enter fullscreen mode Exit fullscreen mode

Conclusion

As always, I hope you found it interesting. If you noticed any errors in this article, please mention them in the comments. 🧑🏻‍💻

Hope you have a great day! 🙌

Oldest comments (2)

Collapse
 
aboss123 profile image
Ashish Bailkeri

Nice Guide!

Collapse
 
franciscomendes10866 profile image
Francisco Mendes

Thank you ✊