WhoBuilt

I Built a File-Based Router for React Native

May 5, 2025· 24 min· 434 views·Watch on YouTube

Speaker

Szymon Chmal, a senior software engineer at Callstack and a web developer, explains how he built an experimental file-based router for React Native in one weekend at the React Universe Meetup.

Why build a file-based router

Chmal wanted to explore how file-based routing works and challenge himself while taking on more management tasks. React Native apps commonly use React Navigation, where screens and nested navigators form a component hierarchy. His experiment aimed to represent that hierarchy with directories and files, while supporting URL-style navigation and dynamic parameters.

Loading screens with Metro

Metro does not allow arbitrary runtime `require` calls: imports need literal paths, and module IDs can change between builds. Chmal first tried generating a manifest and watching the app directory for changes, then found Metro’s unstable `require.context` API. With `unstable_allowRequireContext` enabled, it can include files from a specified directory and make them available to the router.

Building and matching the route tree

Chmal represented each route as a tree node containing its segment name, path, screen component, and child nodes. The router traverses the tree to build React Navigation screens and match URL segments. It checks static routes before dynamic ones, so a route such as `/latest` is not swallowed by a slug parameter.

Adding loading, error, and screen options

Special `loading` and `error` files let the router wrap screens in Suspense and an error boundary. Chmal stored those components on route nodes and used a custom route component to apply the wrappers. He also supported a `screenOptions` export, passing options such as header visibility or title through to React Navigation.

Demo results and limitations

In the demo, screens received URL parameters, an intentional render error showed the custom error component, and a Suspense-triggering promise showed the loading component. Chmal cautioned that the weekend project was not production-grade: it lacked nested navigators such as tabs, route fallbacks, and a not-found page, and its performance and tree structure needed work.

Takeaways

  • Metro’s `require.context` can support file discovery while keeping imports statically analyzable, though the API is marked unstable.
  • Check static routes before dynamic segments to avoid broad parameter routes capturing specific paths.
  • Route metadata can drive loading and error boundaries as well as navigation screen options.
  • A working routing prototype still needs nested navigation, fallback behavior, not-found handling, and performance review before production use.

Mentioned in this talk

Search inside this talk

What was claimed 6

Related talks