Expo announced the release of Expo Router v3 in January 2024, marking it as the first universal, full-stack React framework. Expo Router launched about a decade ago, and this release reflects its attention to the continued changes in the mobile and fronted landscape.
A decade ago, mobile development was split up into iOS and Android. Then, React Native came on the scene and allowed for cross-platform development. Finally, Expo came and made mobile development easier than ever.
Today, Expo is a full suite of tools and services that allow developers to create truly cross-platform applications, mobile and web, and to do so completely in React. Together with Expo Router, Expo makes it easier than ever to implement navigation that will work on both mobile devices and the web seamlessly.
In this article, we’ll discuss Expo Router, its key features, and how it measures up to React Navigation to help you assess whether adopting this tool is the right decision for your next project.
Before we talk about Expo Router, it’s important to learn about the framework it’s based on: React Native.
As we mentioned earlier, before React Native was created in 2015, iOS and Android development was split. This split doubled development time and required companies to hire two types of developers if they wanted their apps in both the Apple Store and the Google Store.
During an internal hackathon, Meta invented React Native, a framework based on JavaScript that supported cross-platform development. Thanks to this framework, JavaScript developers specializing in web development could also work on mobile development for Android and iOS applications.
Expo is an open source platform built on React Native that allows developers to create applications that run on Android, iOS, and the web. It includes a suite of tools and services to build, run, and test native applications. Expo Router is probably one of the most popular Expo tools and is incredibly practical for handling navigation in a mobile application.
At first, Expo Router used the standard concept of stacks to create pages and navigate between them. The idea was that screens would be placed on top of each other in a stack, similar to the first-in-last-out principle.
Since then, Expo Router has moved away from this navigation philosophy and now uses a file-based router to implement the navigation. If you’ve worked with Next.js, you’re likely familiar with this concept already.
In file-based routing, anytime a file is added to the app directory, a new route is created:
/app --> index.js matches '/' --> about.js matches '/about' --> /dashboard --> index.js matches '/dashboard' --> login.js. matches 'dashboard/login'
This type of routing makes it truly cross-platform, as it can also be used on the web, which isn’t possible with the mobile-only stack approach.
Now that we have gone over what Expo Router is, let’s go over some reasons you might consider using it:
npx create-expo-app@latest
) and run it with another (npx expo start
). There are no external libraries to install, and the famous Metro bundler compiles and creates the build for you to test and debug your native applicationOf course, it’s also important to weigh Expo Router’s drawbacks as you consider whether you should choose it. A few cons to keep in mind include:
Overall, Expo Router is a great choice for developers creating mobile applications. It’s both simple and yet filled with features and tools to get up to speed quickly. Its thriving community also ensures that there will be tons of resources to help you out if you’re just getting started with Expo Router.
Creating an Expo application is very easy. Like Create React App, there is a command that will create a sample application:
npx create-expo-app@latest --template tabs@50
This will generate a simple application with Expo Router already set up using a tabs
template at version 50
. You can then run the project with npx expo start
. Once done, you should see this:
Expo Router has some key features that are helpful to understand as you evaluate this framework. Let’s go through them now.
As mentioned above, Expo Router uses file-based routing logic, meaning that every file added to the app directory is a new route. You can also create html-specific routes along with dynamic routes.
Header and tab bars are created using layout files. By calling the _layout.js
file, you can specify your layout, which will wrap around the routes to persist the layout across different pages.
Navigation between pages is done through links, either with the <Links />
React component or the <a>
element. This navigation approach comes closer to how navigation is done on the web.
Expo’s sample project, for example, has this structure:
/app --> modal.tsx // modal component --> _layout.tsx // specifies the layout (headers, tabs, ...) --> +html.tsx // HTML-specific to configure root HTML --> +not-found.tsx // 404 pages --> (tabs) // This is a dynamic route for / or /(tab-number) --> index.tsx // matches '/' --> two.tsx // matches '/two' --> _layout.tsx // layout for the tab pages
Deep linking is the process by which a user will click on a link outside of your app and be redirected to either a specific part of the app or the App Store to download the app. It’s helpful when you need to direct a user to your app from elsewhere, such as from a webpage.
There isn’t any configuration needed, as deep linking comes out-of-the-box with Expo Router. Since Expo Router uses file-based routing, you already have the URLs by default — i.e., /auth/login
. No prefix is required, as Expo Router handles it.
You do, however, need to set up your scheme in your app.json
config file, like so:
{ "scheme": "your-app-scheme" }
You can test your links with uri-scheme
. See Expo Router’s documentation on the subject to help you.
Expo applications can work with third-party React Native libraries or custom native code. Expo router uses autolinking to link native dependencies to the Expo project.
Autolinking enables developers to integrate third-party libraries easily and without additional configuration. You simply have to run npm install
and rerun pod install
.
Many developers have used Expo Router simply because it’s easy to use, but it’s important to note whether a framework is scalable. Realizing the technology you used in your MVP doesn’t scale with your growth can be frustrating, especially if you have to discard and rebuild the entire project.
This is why it’s interesting to see which customers use Expo and why. Thankfully, Expo has a list of customers on their website, many of whom explain their particular use case and why Expo Router is the best fit for their needs.
Insider, for example, explains that they moved to Expo to move away from the development split between iOS, Android, and web that required them to hire three developers to support what should essentially be the same product. The team had a proof of concept in a week and a fully redesigned, multi-platform app nine months later.
Goody, on the other hand, used Expo from the start. What they liked was the out-of-the-box tools that came with Expo. Push notifications, for example, work as is which was a vast improvement from React native which asks for an SDK or a push notification server. This ease of use made the development much faster than had they chosen React Native.
From these example customer stories, you can see that the list of Expo Router’s out-of-the-box features and its quick setup can allow your team to reduce development-related costs and time by maintaining only one application. Your team could also become more efficient, as Expo Router can help you create new features more quickly.
The main alternative to Expo Router is React Navigation. Both frameworks were developed by the Expo team. For developers who don’t want the Expo SDK or are unfamiliar with file-based routing, using React Native with React Navigation would be your good choice.
Let’s go over their main differences:
Let’s summarize this information in a table so you can compare the two options at a glance:
Expo Router | React Navigation | |
---|---|---|
Features | File-based navigation logic Cross-platform (iOS, Android, Web) Deep linking Expo tools (Metro bundler,…) |
Stack and Drawer navigation logic Web support Deep linking Server rendering |
Performance | Near native | Near native |
Community | Strong community | Strong community |
Documentation | Extensive | Extensive |
Uses Cases | Great for developers wanting something out of the box with lots of tools and services. | Great for developers wanting more flexibility when customizing their navigation. |
Expo Router provides a file-based routing solution offered by the Expo team with crucial features such as deep linking and native support.
Expo has been widely popular for the last ten years, and it’s easy to see why. The Expo Router documentation is extensive and includes example repositories, and there’s a thriving community of developers you can seek help from and engage with.
Whether you are trying to learn mobile development or working on a production application, Expo Router is a good choice for you.
Install LogRocket via npm or script tag. LogRocket.init()
must be called client-side, not
server-side
$ npm i --save logrocket // Code: import LogRocket from 'logrocket'; LogRocket.init('app/id');
// Add to your HTML: <script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script> <script>window.LogRocket && window.LogRocket.init('app/id');</script>
Hey there, want to help make our blog better?
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 manage memory leaks in Rust, avoid unsafe behavior, and use tools like weak references to ensure efficient programs.
Bypass anti-bot measures in Node.js with curl-impersonate. Learn how it mimics browsers to overcome bot detection for web scraping.
Handle frontend data discrepancies with eventual consistency using WebSockets, Docker Compose, and practical code examples.
Efficient initializing is crucial to smooth-running websites. One way to optimize that process is through lazy initialization in Rust 1.80.