Simple routing in React Native with React Native Easy Router

Christian Chown
Aug 30, 2018 · 4 min read

Things have improved in the React Native routing ecosystem— there are no longer several “official” navigators competing with community efforts — but the currently popular libraries still seem unwieldy, overly prescriptive and not performant enough.

I’ve used react-navigation (as a hopefully helpful early adopter), and react-native-router-flux extensively, but have been on the lookout for an alternative that would:

  • Be simple —I just want to specify routes, and have functions to change the stack of screens displayed
  • Not prescribe UI —yes, I want pretty tabs and drawers, but I want those determined by my app, not the router
  • Have elegant screen transitions

Sergey Shpadyrev’s react-native-easy-router fits the bill. I’ve made a few contributions to the library myself.

A simple but illustrative example app

Firstly, I have a logged out section, where you would fill out a login form or click on a social login button to authenticate yourself.

Simple unauthenticated route

I also have an authenticated section with tabs, a drawer and screens to visit.

For each of these application states, I have a different EasyRouter instance. You could just as easily have a single EasyRouter instance and manage the authenticated/unauthenticated stack yourself.

const authenticatedRoutes = {
intro: IntroScreen,
login: LoginScreen
};
const unauthenticatedRoutes = {
home: HomeScreen,
settings: SettingsScreen,
profile: ProfileScreen
};
...{authenticated ? (
<EasyRouter routes={authenticatedRoutes} initialRoute="intro" />
) : (
<EasyRouter routes={unauthenticatedRoutes} initialRoute="home" />
)}

The router object

Each of the pop/push/replace/reset navigation functions can specify:

  • parameters passed to the screen component, as well as
  • animation — which comprise a transition type (none, bottom, left, right, top, left-bottom, left-top, right-bottom, right-top and fade are all built-in), and an optional duration and easing

So with a routerobject, you navigate by:

router.push.ScreenToGoTo(
{param1: 'value1', param2: 'value2'},
{type: 'fade'},
);

Which would make ScreenToGoTo fade in with param1, param2 and router in its props.

Adding UI — tabs and drawers etc.

In the example App, I set this router object to state, and then pass it via props to UI components like a <Drawer> or <Tabs>

<DrawerComponent
router={this.state.router}
>
<TabsComponent
router={this.state.router}
>
<EasyRouter
{...props}
router={router => {this.setState({router})}}
/>
</Tabs>
</Drawer>

Prop drilling like this isn’t the only option to give non-screen components access to navigation methods; the router callback prop could just as easily store the router object in a singleton, Context or other store that components can access.

Redux integration

<EasyRouter
{...props}
onStackChange={newStack => {
dispatch({type: 'SET_ROUTER_STACK', payload: newStack});
}}

/>

Custom transitions

const animations = {
effect: [
// start
{
opacity: 0,
transform: [{scale: 0}],
},
// end
{
opacity: 1,
transform: [{scale: 1}],
},
// useNativeDriver
true
],
}
<EasyRouter
{...props}
animations={animations}
/>
// in some other componentthis.props.router.push.Screen({}, {type: 'effect'});

Animating UI to match navigation transitions

<Tabs
transition={this.state.transition}
from={this.state.from}
to={this.state.to}
>
<EasyRouter
onBeforeStackChange={(transition, oldStack, newStack) => {
this.setState({
transition,
from: oldStack[oldStack.length-1].route,
to: newStack[newStack.length-1].route
})
}}
/>
</Tabs>

Shouldn’t the library support nested routers and have built-in drawers, tabs, modals, title headers and so on, like other navigation libraries?

Routing in React Native needn’t be complex, and with react-native-easy-router, it needn’t be for you, either.

Christian Chown

Written by

Hello! I’m a software developer based in the UK. I write niche articles about Firebase, React, React Native and other development bits and bobs