React Native Project Standards

There's no reason you can't or shouldn't follow a directory-setup like we describe on our normal Project Standards page.

Intro to React Native

Basic UX for Touch Devices

Cancellation - Give your users the ability to "cancel" a touch/gesture right in the middle of it (for example, by dragging their finger away). Read more about gesture best practices here.

Stick to Buttons With Visual Feedback - Various buttons provided by React Native have their own feedback controls which provides visual aid to the user. It is recommended best practice to implement visual feedback for a gesture touch to keep the user informed of action results. Traditionally, this would've been implemented with things like TouchableOpacity - but the recommended component to use for future apps would be the Pressable.

Ecosystem / Packages

A very useful directory for browsing open source packages and functionality you should consider using is the React Native Directory. You can filter by the platform you're deploying to as well.

Furthermore, there will be times you need to use "Native Modules" to interact with device-specific APIs that JavaScript cannot provide. At the time of writing, Native Modules and Native Components are deprecated and will eventually transfer to the new and improved Turbo Native Modules and Fabric Native Components. For more info, visit the Native Modules Intro from the docs.

Component Tips

There's nothing particularly unique in React Native that would keep you from implementing the same general project practices we recommend on our Project Structure page. So for organizing your component files and folder structure we do recommend the same approach.

However, there are some particular catches when developing with React-Native, so we'll try to explain those below:

React Native Quick Tips

// Occasionally you will run into scenarios where Platform-specific code is required.
// You can use the Platform import for these purposes.
import { Platform, StyleSheet } from 'react-native'

// <SafeViewArea> & <Flatlist> are two critical components you should frequently use
// SafeViewArea - To ensure your views don't get cut off by odd iPhone screen shapes (wrap your View layer in this)
import { SafeAreaView } from 'react-native'
// FlatList - an extremely performant method of rendering list-like components. Uses virtualization under the hood.
import { FlatList } from 'react-native'

// Conditionally apply styles depending on platform of user
const styles = StyleSheet.create({
  container: {
    flex: 1,
    ...Platform.select({
      ios: {
        // iOS-only styles
      },
      android: {
        // Android-only styles
      },
    }),
  },
})

// or, reference the Platform.OS property directly to conditionally run code in your components
switch (Platform.OS) {
  case 'ios':
  case 'android':
  case 'macos':
  case 'windows':
  case 'web':
}

if (Platform.OS === 'ios' || Platform.OS === 'android') {
  // target whichever system you need
}

Performance & Optimization Tips

With React Native being a leader in producing mobile applications, it is imperative to consider performance caveats and best practices. For more, please refer to the React Native Performance Overview Docs. Below are some misc tips for optimization.

Image performance is a crucial when working with a native application as memory constraints means unoptimized image use could lead to crashes, especially when using static image resources. Here are a number of ways to handle for this.

  • react-native-fast-image package - Provides a FastImage component that integrates with the SDWebImage(iOS) and Glide (Android) objects which, as you guessed, loads images much faster.
  • Proper image Formats - You may want to consider using formats like PNG or WEBP format for reducing binary size of images for both platforms. This can reduce images to 1/3 of the original size.

RAM Format - For iOS, you can produce your application in RAM format for a single indexed file. As the docs state:

"... This is useful for apps that have a large number of screens which may not ever be opened during a typical usage of the app. Generally it is useful to apps that have large amounts of code that are not needed for a while after startup..."

With use of Hermes, this is enabled by default.