How React Native Screens powers Expo Router?

Tymoteusz Boba
Software Mansion
Published in
6 min readFeb 8, 2024

--

If you want to make the navigation in your application better, there are plenty of solutions that you can choose from. There is the React Navigation library, which is a default choice for most of the programmers. There is Solito, a wrapper around React Navigation that allows you to build cross-platform apps with Next.js. There is also the Expo Router library, which has become increasingly popular recently. It enriches the way of creating navigation with new awesome solutions.

What do all these libraries have in common? Each of them uses
react-native-screens under the hood!

Today, I’d like to focus more on Expo Router — in particular, how it’s powered by react-native screens, a library maintained by Software Mansion.

What is Expo Router?

Expo Router is a library created by Expo, which was officially announced 1.5 years ago. It uses React Navigation for navigating between screens, just like Solito does. What makes it different is that Expo Router lets you define your navigation structure using files similarly to how Next.js works. It shares the concept of a file-based router, which means that each file represents a single path. That’s why in Expo Router you can create a file under an app directory to make it resolve your screen to a specific route. For example, for creating a /home path, you can create a file in app/Home.tsx to make it work straight away.

Expo Router also provides many more features. You can define a file that will be responsible for the layout of your app, create a dynamic route, or even define error boundaries around the screen. But, for the purpose of this article, I want to specifically focus on the things that provide a native feel of navigating between your views. How did Expo Router achieve such behaviour?

Credits: Evan Bacon (https://blog.expo.dev/announcing-expo-router-v1-1d97d7833605)

Expo Router ❤️ React Native Screens

𝚛𝚎𝚊𝚌𝚝-𝚗𝚊𝚝𝚒𝚟𝚎-𝚜𝚌𝚛𝚎𝚎𝚗𝚜 is a library that allows developers to create a native stack of the views on Android and iOS. React Navigation uses it to create a native stack inside the @𝚛𝚎𝚊𝚌𝚝-𝚗𝚊𝚟𝚒𝚐𝚊𝚝𝚒𝚘𝚗/𝚗𝚊𝚝𝚒𝚟𝚎-𝚜𝚝𝚊𝚌𝚔 package. It also provides a simple API that you can use to create your own navigation library. For example, React Navigation uses components provided by React Native Screens, such as ScreenContainer or ScreenStack to manage and operate native navigation. Since we know that Expo Router uses React Navigation’s native stack under the hood, let’s think it through. What advantages does it take from using Screens?

The biggest advantage

As mentioned before, the stack that Expo Router manages is native. It means that all the components that you see on the screen — a header, a stack, and even a screen are being managed by OS-specific controllers (UINavigationController on iOS and FragmentManager on Android). That’s why every screen you can see while using Expo Router looks and behaves natively. What’s more interesting is that you can control the look of the currently shown screen by just changing its props. Creating a _layout.js file in the app directory, making the structure of your desired navigation, and defining the screen options are all you need to make the layout and change the appearance of your application. The native side will take care of everything for you.

With Expo Router, you can also choose an alternative for the native stack, which is a stack controlled only on the JS side. It offers more flexibility, but the components I’ve mentioned earlier are not managed by OS-specific controllers. It only mimics the familiarity of iOS and Android navigation by rendering and animating components, made with pure React Native.

Simple structure of _layout.js file

Memory performance boost 🚀

Because of the power that comes from react-native-screens, Expo Router gains a huge performance boost by unmounting inactive screens. What does it mean?

When a user goes from one screen to another, the content of the previous screen is detached, resulting in unmounting its content. Because of that, react-native-screens keeps only the components that are visible to the user, which saves the memory of the device. The state of the previous screens is still preserved in the React component tree, but react-native-screens ensures all the content in inactive screens is gone.

How does it work in practice? Let’s take a look at the view hierarchy to compare the memory usage with and without the use of react-native-screens:

We can see that with the use of react-native-screens not only the view hierarchy is slimmer, but also memory usage has dropped from 230mb to 168mb.

Easy to use

Last but not least, Expo Router is easy to use because of all the things that React Navigation has brought before. As Expo Router is still a wrapper of React Navigation, it uses all the components and props that are used in the native stack. That’s why if you have previously used it, you’ll be familiar with the process of creating navigation in Expo Router. For example, headerTitle prop still handles changing the title shown on the top, headerShown prop still changes the visibility of the header and presentation prop still allows you to control the presentation of a screen. All you have to do is change the prop inside the options object to adjust the behaviour of the components you can see on the screen. All of those things are possible, because of the power of React Navigation’s native stack and react-native-screens that work under the hood of Expo Router.

Final words

From what we’ve covered today, we can clearly say that Expo Router is a really powerful player, compared to other navigation libraries. Not only does it improve the ease of creating app navigation, but it also offers unparalleled features that simplify making more advanced routes. Thanks to react-native-screens, it gains a memory performance boost, adds a natural feel to your application, and uses the APIs that you already probably know.

Yet, even if Expo Router has so many advantages, it does not mean it’s the only right choice among all navigation libraries. React Navigation is just fine. If your application is already using React Navigation, I wouldn’t throw myself in at the deep end and rewrite it to Expo Router. Still, I’m convinced that it is a great library to consider and one that I’d give a shot.

If you want to deep dive into more advanced topics about Expo Router, check out the App.js Conf workshop about using Expo Router here.

Also, if you like Expo Router and want to learn more, see the documentation. You can also take a look at react-native-screens on GitHub.

--

--