Youssouf El Azizi A human first 🙌, full-stack web developer 👨🏻‍💻 and OSS believer. I love working with React and React Native.

The best React Native libraries for leveraging native features

7 min read 2159

React Native Ui Libraries Native Features

The React Native community is one of the more vibrant open source communities on the web. According to GitHub, the React Native repository is one of the top-rated repos based on the number of contributors. You can find modules and third-party libraries for almost anything you want to implement in your next mobile application.

You’re bound to encounter issues related to deprecated and unmaintained packages, especially packages from the early days of React Native — it’s simply a fact of life. I think it’s an acceptable burden since maintaining a React Native library requires maintaining a project that can depend on at least three languages.

React Native UI libraries every mobile developer should know

It is crucial to know which libraries to use to create the best possible user and developer experience. In this tutorial, we’ll introduce you to 15 React Native UI libraries that I’ve used in virtually every React Native application I’ve worked on so far in 2021.

We’ll cover the best React Native UI libraries for:

Then, we’ll go over some tips and best practices for using these and other React Native UI libraries, including how to:

React Native UI Lets Go Gif

Styling

Styling is a very opinionated topic in the React community and JavaScript communities in general. I have used almost all CSS-in-JS approaches to style my React and React Native applications. I’ve settled on using Tailwind CSS for web and Restyle for React Native.

Restyle is a library developed by Shopify with a type-enforced system for building UI components. With Restyle, you can make a complete design system by defining colors, spacing, and variations and creating your components based on React Native core components and Restyle utilities.

The best feature of Restyle is that it forces you to use only configurations you already declared in your theme, which keeps the application clean and guides your coworkers by keeping their choices as minimal as possible.

Restyle requires you first to create a theme that reflects your design system config (colors, spacing, breakpoints, and variants), like this:

We made a custom demo for .
No really. Click here to check it out.

import { createTheme } from '@shopify/restyle'

const palette = {
  purpleLight: '#8C6FF7',
  purplePrimary: '#5A31F4',
  purpleDark: '#3F22AB',

  greenLight: '#56DCBA',
  greenPrimary: '#0ECD9D',
  greenDark: '#0A906E',

  black: '#0B0B0B',
  white: '#F0F2F3',
};

const theme = createTheme({
  colors: {
    mainBackground: palette.white,
    cardPrimaryBackground: palette.purplePrimary,
  },
  spacing: {
    s: 8,
    m: 16,
    l: 24,
    xl: 40,
  },
  breakpoints: {
    phone: 0,
    tablet: 768,
  },
});

export type Theme = typeof theme;
export default theme;

This what your components will look like using Restyle:

React Component View Restyle

If you had asked me two years ago, I would’ve cautioned against using React Navigation due to some performance challenges and recommended using a native library, such as React Native Navigation, instead.

Fortunately, the React Navigation community, with some help from Software Mansion, developed and optimized three of the most-used libraries in the React Native ecosystem: React Native Screens, React Native Gesture Handler, and React Native Reanimated. Those three libraries are the secret behind the huge performance improvement you’ll notice starting from version 4.

Today, React Navigation should be your first choice; you don’t need to think twice.

To start working with React Navigation, you must first install all its dependencies:

yarn add react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context @react-native-community/masked-view

You can use three common types of navigator with React Navigation: Stack, Tab, and Drawer. You can also combine multiple navigators and create a complex app architecture.

Here’s a simple example of a stack navigator:

   import { createStackNavigator } from '@react-navigation/stack';

const Stack = createStackNavigator();

function MyStack() {
  return (
    <Stack.Navigator>
      <Stack.Screen name="Home" component={Home} />
      <Stack.Screen name="Notifications" component={Notifications} />
      <Stack.Screen name="Profile" component={Profile} />
      <Stack.Screen name="Settings" component={Settings} />
    </Stack.Navigator>
  );
}

Splash screens

Adding a splash screen to your mobile application is a tedious task, and the best way to accomplish tedious tasks is to automate them. react-native-bootsplash enables you to create a fancy splash screen using CLI. All you need to do is provide an image and background color and the package will do the work for you.

I prefer using react-native-bootsplash over the most popular package, react-native-splash-screen, because the former prevents you from seeing the red errors if you’re facing an issue on startup and sticks on the splash screen instead, which is annoying.

The following command generates a splash screen in react-native-bootsplash:

yarn react-native generate-bootsplash assets/bootsplash_logo_original.png \
  --background-color=F5FCFF \
  --logo-width=100 \
  --assets-path=assets \
  --flavor=main

Splash Screen React Native Bootsplash Display

App icons

This is another tedious chore we need to automate. To automate generating app icons, we’ll use a plugin called React Native Make. The plugin is available through the React Native CLI and is designed to help you generate app icons for iOS and Android platforms.

To use react-native-make, you just need a 1024×1024 version of your app icon and you’re ready to generate app icon assets using the following commands:

react-native set-icon --path path-to-image

Loading placeholder

One of the most common questions I receive about React Native mobile apps is how to create a loading experience similar to apps such as Facebook and YouTube.

There are multiple solutions to create such an experience, but I would recommend using the react-content-loader package. This package is based on the react-native-svg and Reanimated libraries, which seem to work very smoothly. The package also provides a playground to help you create a placeholder in your browser.

Here’s an example of a loading placeholder similar to that in the Facebook app:

import React from "react"
import ContentLoader, { Rect, Circle, Path } from "react-content-loader/native"

const MyLoader = (props) => (
  <ContentLoader 
    speed={2}
    width={400}
    height={460}
    viewBox="0 0 400 460"
    backgroundColor="#d1d1d1"
    foregroundColor="#c4c4c4"
    {...props}
  >
    <Circle cx="31" cy="31" r="15" /> 
    <Rect x="58" y="18" rx="2" ry="2" width="140" height="10" /> 
    <Rect x="58" y="34" rx="2" ry="2" width="140" height="10" /> 
    <Rect x="0" y="60" rx="2" ry="2" width="400" height="400" />
  </ContentLoader>
)

export default MyLoader

Loading Placeholder Example

Handling and tracking errors

We all aim to make our React Native application bug-free by using a typing system and increasing testing coverage. However, even with high testing coverage, users are still sure ti encounter and report bugs.

Therefore, it’s crucial to handle your errors and provide feedback to users whenever the app is not working as expected. react-native-exception-handler offers a simple way to handle native and JavaScript errors and deliver feedback to users.

To make react-native-exception-handler work, you must install and link the module. Next, register your global handler for JavaScript and native exceptions, like so:

import { setJSExceptionHandler, setNativeExceptionHandler } from "react-native-exception-handler";

setJSExceptionHandler((error, isFatal) => {
  // This is your custom global error handler
  // You do stuff like show an error dialog
  // or hit google analytics to track crashes
  // or hit a custom api to inform the dev team.
});

const exceptionhandler = (exceptionString) => {
  // your exception handler code here
};
setNativeExceptionHandler(
  exceptionhandler,
  forceAppQuit,
  executeDefaultHandler
);

You should track these errors with a third-party tool that notifies you of the errors users encounter in your application so you fix them in future releases.

Fetching data

My suggestion in this section will depend on your back-end implementation. If you are using a REST API, react-query is your best choice here. But instead, if you’re using graphQL, you can use urql. Those two libraries will provide you with everything you will need to handle API in your application. You will benefit from a ton of unique features like caching, offline support, optimistic UI, prefetching, and much more.

After installing react-query you can create your own hook to fetch tasks as example:

import {useQuery} from 'react-query';
import {client} from './client';

const getTasks = async () => {
  const {data} = await client.get('/tasks');
  return data;
};

export function useTasks() {
  return useQuery('tasks', getTasks);
}
```
And use it inside your components to fetch tasks : 

```
export const Tasks = () => {
  const {isLoading, data} = useTasks();

  if (isLoading) {
    return <ActivityIndicator color="#000" />;
  }
  return (
    <FlatList
      ListHeaderComponent={() => <Header />}
      data={data || []}
      renderItem={({item}) => <TaskItem {...item} />}
      keyExtractor={(_, index) => `item-${index}`}
      showsHorizontalScrollIndicator={false}
    />
  );
};

Icons

Most articles I’ve seen about using icons in React Native suggest using React Native Vector Icons as a default choice. It’s true that this library has numerous icons and fonts, but more often than not, my team found itself creating new fonts to accompany custom designs in our icons. In my opinion, creating a custom font with react-native-vector-icon makes for a suboptimal experience because you need to generate a new font whenever you want to add a new icon.

Instead, my team start using react-native-svg for our icons with the amazing SVGR package, which can generate a React component from any SVG file. You can even directly export a React component from a Figma file.

Below is a simple example of an SVG icon generated as React Native components using the SVGR Figma plugin:

import * as React from "react"

function Icon(props) {
  return (
    <svg
      width={48}
      height={1}
      viewBox="0 0 48 1"
      xmlns="http://www.w3.org/2000/svg"
      {...props}
    >
      <title>{"Rectangle 5"}</title>
      <path d="M0 0h48v1H0z" fill="#063855" fillRule="evenodd" />
    </svg>
  )
}

export default Icon

Images

If your application depends mainly on images, you’ll notice some performance issues, especially with lists and scroll view.

Using FastImage, a performant React Native image component, will help you improve your application without any extra effort. It exactly replaces the image component from React Native and adds some amazing features, such as caching and prioritizing and reloading.

Forms

There are some great solutions out there for handling forms in React Native, including Formik and React Hook Form.

I used to use Formik, but I’ve been hooked on React Hook Form ever since I discovered it. In my opinion, this is the best solution for handling simple and complex forms in React.

Other benefits of using React Hook Form include state management, validation, errors management, and multiple array fields.

Testing

If you’ve already worked with the testing libraries to test your frontend applications, your knowledge and experience will be applicable to testing in React Native. React Native Testing Library has virtually the same API.

Here’s a simple counter unit test using React Native Testing Library:

import "react-native";
import React from "react";
import { fireEvent, render } from "@testing-library/react-native";

it("renders correctly", () => {
  // render component
  const { getByText } = render(<Counter />);

  // get buttons and text elements
  const decrement = getByText(/decrement/i);
  const increment = getByText(/increment/i);
  const counterText = getByText(/Current count:/i);

  // Make sure you have the right values
  expect(counterText.props.children).toEqual(["Current count: ", 0]);
  // trigger an event
  fireEvent.press(increment);
  expect(counterText.props.children).toEqual(["Current count: ", 1]);
  fireEvent.press(decrement);
  expect(counterText.props.children).toEqual(["Current count: ", 0]);
});

To test your application’s behavior with confidence, I would recommend writing end-to-end tests using the Detox library from Wix.

Tips and best practices for using React Native UI libraries

Below are some bonus tips to help you get the most out of the React Native libraries detailed above.

Create a React Native template

If you expect to use all these libraries in your upcoming React Native projects, it might be worth your time to create a simple template so you can easily start a new project.

We recently created a template for our mobile team to start new projects with all the aforementioned libraries. Here it is if you want to use it:

npx react-native init MyApp --template https://github.com/obytes/react-native-template-obytes

Get updates about new libraries

One of the most effective ways to get updated about new libraries and best practices is to follow open source projects. I like to check the package.json file for every React Native project shared on my network. Whenever I find a new library, I search for it to learn more.

Also, be sure to follow the react-native topic on GitHub explore page. You’ll receive a ton of React Native projects and discussions.

Use TypeScript with React Native

I started using TypeScript as the primary language for React Native projects about a year-and-a-half ago, and I wish I had done so earlier. Using TypeScript helps you improve the quality of your code and the developer experience because it helps you prevent errors while typing and improve autocomplete functionality.

It’s important to note that TypeScript is only a JavaScript superset with optional static typing. It doesn’t require you to learn a whole new language.

Conclusion

I hope you found this React Native tutorial interesting, informative, and entertaining. We discussed the benefits of using React Native libraries to leverage native features in your mobile app, recommended specific tools to help you with styling, debugging, data fetching and more, and outlined some tips and best practices to help you get the most out of these React Native libraries.

: Full visibility into your web apps

LogRocket is a frontend application monitoring solution that lets you replay problems as if they happened in your own browser. Instead of guessing why errors happen, or asking users for screenshots and log dumps, LogRocket lets you replay the session to quickly understand what went wrong. It works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store.

In addition to logging Redux actions and state, LogRocket records console logs, JavaScript errors, stacktraces, network requests/responses with headers + bodies, browser metadata, and custom logs. It also instruments the DOM to record the HTML and CSS on the page, recreating pixel-perfect videos of even the most complex single-page apps.

.
Youssouf El Azizi A human first 🙌, full-stack web developer 👨🏻‍💻 and OSS believer. I love working with React and React Native.

2 Replies to “The best React Native libraries for leveraging native features”

  1. You should take a look at the Navigation router, https://grahammendick.github.io/navigation/native/. It’s 100% native on iOS and Android and leverages more native features than React Navigation (or React Native Navigation). Its TabBar component, for example, renders to the UITabBarController on iOS and BottomNavigationView on Android. It’s the only navigation library that offers a native collapsing header on Android, backed by the CoordinatorLayout. Here’s an example you can run that shows a native search bar on Android and iOS and a native shared element transition on Android, https://github.com/grahammendick/navigation/tree/master/NavigationReactNative/sample/zoom

Leave a Reply