Why I Switched to React Native to Create a Super Easy Bottom Sheet

As a full-stack developer, I‘ve had the opportunity to work with a wide range of technologies at different layers of the stack. On the backend, I‘ve built APIs and services using Node.js/Express, Ruby on Rails, and even experimented with serverless functions in cloud environments. For the web frontend, I‘ve worked extensively with React, Angular, and Vue.js to create interactive and responsive user interfaces.

More recently, I was tasked with building a mobile app for both Android and iOS. In the past, I had done some Android development with Java and a bit of iOS work in Objective-C and Swift. However, the thought of having to maintain two separate native codebases for a relatively simple app didn‘t appeal to me.

That‘s when I decided to give React Native a try. I had heard good things about it from colleagues and seen some impressive apps built with it, like Facebook, Instagram, and Airbnb (source: Ideamotive). The prospect of being able to leverage my existing React skills and write a single codebase that runs on both mobile platforms sounded amazing.

Adoption of React Native has grown steadily since its release in 2015. According to the 2020 Stack Overflow Developer Survey, React Native is the 6th most popular framework, library, or tool, used by 11.5% of professional developers. A separate survey by Applitools found that 42% of companies use React Native for their mobile apps.

So I decided to dive in and start building my app with React Native. One of the first things I needed to add was a bottom sheet for selecting filters on a search screen.

What is a Bottom Sheet?

A bottom sheet is a UI panel that slides up from the bottom of the screen to reveal additional content or actions. It‘s commonly used for:

  • Sorting, filtering, or refining content
  • Selecting from a list of options
  • Presenting more details or settings
  • Confirming or canceling an action

Bottom sheets are part of Google‘s Material Design guidelines for mobile apps. According to the Material Design spec, bottom sheets are "surfaces containing supplementary content that are anchored to the bottom of the screen."

The spec recommends that bottom sheets be used for:

  • Providing access to a feature or specific task without leaving the current context
  • Presenting deep-linked content from other parts of the app
  • Supporting tasks like sharing, creating, or setting options

Some examples of popular apps that use bottom sheets include:

  • Google Maps: Shows details about a selected location, like business hours, reviews, and photos
  • Uber Eats: Allows filtering restaurant search results by price, rating, cuisine, and more
  • Airbnb: Displays date pickers for selecting check-in and check-out when searching for stays

Here‘s a visual example of a bottom sheet from the Google Maps app:

[Insert image of Google Maps bottom sheet]

Source: Material Design

Implementing a Bottom Sheet in React Native

To add a bottom sheet to my React Native app, I used the react-native-raw-bottom-sheet library. This library provides a highly customizable bottom sheet component that uses native views and animations for smooth performance.

Installing the library is simple with npm:

npm install react-native-raw-bottom-sheet

Then I imported it into my component:

import BottomSheet from ‘react-native-raw-bottom-sheet‘;

The basic usage looks like this:

<BottomSheet
  ref={ref => {
    this.bottomSheet = ref;
  }}
  height={300}
  openDuration={250}
>
  {/* Bottom sheet content */}
</BottomSheet>

The ref prop allows you to get a reference to the bottom sheet instance so you can call its open and close methods. The height prop sets the height of the bottom sheet when it‘s fully opened. And openDuration specifies the animation duration in milliseconds.

To show the bottom sheet, I simply called:

this.bottomSheet.open();

And to close it:

this.bottomSheet.close();

I wrapped this in functions that I passed to a button press handler:

openBottomSheet = () => {
  this.bottomSheet.open();
}

closeBottomSheet = () => {
  this.bottomSheet.close(); 
}

render() {
  return (
    <View>
      <Button title="Open" onPress={this.openBottomSheet}/>
      <Button title="Close" onPress={this.closeBottomSheet}/>
      {/* ... */}
    </View>
  );
}

Here‘s a complete example:

import React, { Component } from ‘react‘;
import { View, Text, Button } from ‘react-native‘;
import BottomSheet from ‘react-native-raw-bottom-sheet‘;

export default class SearchScreen extends Component {
  render() {
    return (
      <View style={{ flex: 1 }}>
        {/* Main content */}
        <Text>Search results go here</Text>

        {/* Filter button */}
        <Button 
          title="Filter"
          onPress={() => {
            this.bottomSheet.open();
          }}
        />

        {/* Bottom sheet */}
        <BottomSheet
          ref={ref => {
            this.bottomSheet = ref;
          }}
          height={300}
          openDuration={250}
        >
          <View>
            <Text>Filter options</Text>
            <Button title="Close" onPress={() => this.bottomSheet.close()} />
          </View>
        </BottomSheet>
      </View>
    );
  }
}

This gives you a functional bottom sheet that can be triggered with a button press. You can put whatever content you want inside the BottomSheet component, just like a regular React Native View.

Customizing the Bottom Sheet

The react-native-raw-bottom-sheet library exposes several props for customizing the look and behavior of the bottom sheet. Some key ones include:

  • dragFromTopOnly: Only allow dragging from the top of the sheet (default is false)
  • closeOnDragDown: Close the sheet when the user drags it down (default is false)
  • closeOnPressMask: Close the sheet when the user taps outside it (default is true)
  • customStyles: Override default styles of the sheet, handle, and mask

For example, to create a bottom sheet that closes when dragged down:

<BottomSheet
  ref={ref => (this.bottomSheet = ref)}
  closeOnDragDown={true}
>
  {/* Content */}
</BottomSheet>

To change the color and border radius of the sheet:

<BottomSheet
  ref={ref => (this.bottomSheet = ref)}
  customStyles={{
    container: {
      borderTopLeftRadius: 24,
      borderTopRightRadius: 24,
      backgroundColor: ‘#F1F1F1‘,  
    },
  }}
>
  {/* Content */}
</BottomSheet>

You can find the full list of props in the library documentation.

Advanced Usage

Beyond the basic open/close functionality, you can also integrate the bottom sheet with other parts of your app and UI.

For example, to automatically close the bottom sheet when a selection is made:

<BottomSheet
  ref={ref => (this.bottomSheet = ref)}
>
  <TouchableOpacity
    onPress={() => {
      // Handle selection
      this.setState({ selectedFilter: ‘Recent‘ });
      // Close bottom sheet
      this.bottomSheet.close();
    }}
  >
    <Text>Most Recent</Text>
  </TouchableOpacity>

  <TouchableOpacity
    onPress={() => {
      this.setState({ selectedFilter: ‘Popular‘ });
      this.bottomSheet.close();
    }}
  >
    <Text>Most Popular</Text>
  </TouchableOpacity>
</BottomSheet>

Or to create a custom header for the bottom sheet that stays visible as the content scrolls:

<BottomSheet
  ref={ref => (this.bottomSheet = ref)}
  customHeader={
    <View>
      <Text>Filter Options</Text>
    </View>
  }
>
  <ScrollView>
    {/* Filter options */}
  </ScrollView>
  <Button title="Apply" onPress={this.applyFilters} />
</BottomSheet>

You can even use the bottom sheet with a FlatList or SectionList for optimal rendering of long lists:

<BottomSheet
  ref={ref => (this.bottomSheet = ref)}
>
  <FlatList
    data={this.props.items}
    keyExtractor={item => item.id}
    renderItem={({ item }) => (
      <TouchableOpacity onPress={() => this.selectItem(item)}>
        <Text>{item.name}</Text>
      </TouchableOpacity>
    )}
  />
</BottomSheet>

Why React Native

Coming back to my experience, switching to React Native for this project was a big success. Not only was I able to easily implement a bottom sheet, but the development process was fast and smooth.

Some key benefits I noticed:

  • Familiarity: I was able to use my existing JavaScript and React skills and libraries
  • Code reuse: I could share components and logic between iOS and Android with a single codebase
  • Live reloading: Changes were instantly reflected in the emulator/device without a lengthy build process
  • Performance: The app felt native and performant thanks to asynchronous rendering and native views

Best of all, using React Native didn‘t feel like a compromise. I was still able to implement complex gestures and animations, integrate with native modules when needed, and achieve a polished look and feel that matched the platform design guidelines.

Nader Dabit, a prominent React Native developer and trainer, sums it up well:

"When you are building a React Native app, you are using the same native building blocks that you would in an iOS or Android app, you just don‘t have to deal with the native languages as much." (Source: React Native in Action)

Of course, React Native isn‘t perfect. It has some limitations and pitfalls, like any technology. But for many common use cases, especially for teams with web development experience, it‘s a fantastic option.

Airbnb, an early adopter and major contributor to React Native, used it to build their mobile app for several years before eventually switching back to native for specific technical and organizational reasons. However, even in their postmortem blog post, they praised React Native‘s simple model, fast iteration cycle, and cross-platform features:

"React Native has been invaluable for us at Airbnb … It is an excellent choice for many companies, and it may be the best choice for building simple apps … We‘re glad we were able to provide many benefits to mobile development and beyond."

For my particular use case of quickly adding a bottom sheet to a mobile app, React Native was the perfect fit. It allowed me to create a great user experience with minimal overhead and will enable me to keep my iOS and Android features in sync effortlessly going forward.

Conclusion

Building a bottom sheet—a common mobile UI pattern—is incredibly easy with React Native and libraries like react-native-raw-bottom-sheet. With just a few lines of code, you can add this powerful component to your app and customize it to fit your specific design and interaction needs.

More importantly, React Native itself has proven to be a highly effective way to build mobile apps, especially for developers with a web background. The ability to leverage existing skills, share code between platforms, and still deliver native performance is a game-changer.

If you haven‘t already, I highly recommend giving React Native a try for your next mobile project. It might just change the way you approach app development altogether.

Similar Posts