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.
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:
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:
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:
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> ); }
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
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
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
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.
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} /> ); };
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
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.
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.
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.
Below are some bonus tips to help you get the most out of the React Native libraries detailed above.
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
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.
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.
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.
LogRocket is a React Native monitoring solution that helps you reproduce issues instantly, prioritize bugs, and understand performance in your React Native apps.
LogRocket also helps you increase conversion rates and product usage by showing you exactly how users are interacting with your app. LogRocket's product analytics features surface the reasons why users don't complete a particular flow or don't adopt a new feature.
Start proactively monitoring your React Native apps β try LogRocket for free.
Would you be interested in joining LogRocket's developer community?
Join LogRocketβs Content Advisory Board. Youβll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowLearn how to implement one-way and two-way data binding in Vue.js, using v-model and advanced techniques like defineModel for better apps.
Compare Prisma and Drizzle ORMs to learn their differences, strengths, and weaknesses for data access and migrations.
It’s easy for devs to default to JavaScript to fix every problem. Let’s use the RoLP to find simpler alternatives with HTML and CSS.
Learn how to manage memory leaks in Rust, avoid unsafe behavior, and use tools like weak references to ensure efficient programs.
2 Replies to "The best React Native libraries for leveraging native features"
A lot of these libs are not native at all (not that they need to be) so the title is kinda misleading.
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