react-router-native-navigation v0.2.0
React Router Native Navigation
This repo is still under development
Navigation in react-native is hard. It shouldn't be that way. There are plenty of great libraries out there that can help you create good navigation. This package is the glue you wanted.
As the name suggest, this package is heavily influenced by React Router. The aim is to make it a drop-in replacement for react-router-native as much as possible.
Demo
TODO: Expo Demo and screenshot
Sneak Peak
TODO: Change example to full blown
import React from 'react'
import { View, Text } from 'react-native'
import { NativeRouter } from 'react-router-native'
import { BottomNavigationSwitch } from 'react-router-native-navigation'
export default class App extends React.Component {
render() {
return (
<NativeRouter>
<BottomNavigationSwitch>
<Route exact path="/" render={() => <View><Text>Home</Text></View>} />
<Route path="/settings" render={() => <View><Text>Settings</Text></View>} />
</BottomNavigationSwitch>
<Link to="/"><Text>Home</Text></Link>
<Link to="/settings"><Text>Settings</Text></Link>
</NativeRouter>
);
}
}
Features
- React Router goodness
- Remembers previous screen states
- Handles back button presses
- Custom stack animations
- Allows nesting (I think this should work out of the box but not tested yet)
- Baked in UI
- Lifecycle
- Stack Navigation
- Bottom Navigation
Installation
This package is purely JavaScript so you only need to run:
yarn add react-router-native-navigation
Docs
Switches
These component are the core of this library. They make navigation behave like they should.
\
A switch component that simulates Stack navigation. Only 1 screen is shown at a time. The rest are hidden but are still rendered to preserve their state. Transitions are handled and customizable similar to react-navigation
Usage
import React from 'react'
import { View, Text } from 'react-native'
import { NativeRouter } from 'react-router-native'
import { StackSwitch } from 'react-router-native-navigation'
export default class App extends React.Component {
render() {
return (
<NativeRouter>
<StackSwitch>
<Route exact path="/" render={() => <View><Text>Home</Text></View>} />
<Route path="/settings" render={() => <View><Text>Settings</Text></View>} />
</StackSwitch>
<Link to="/"><Text>Home</Text></Link>
<Link to="/settings"><Text>Settings</Text></Link>
</NativeRouter>
);
}
}
Props
Prop | Type | Default | Description |
---|---|---|---|
mode | string | card | The animation mode. Accepts card or modal . |
transitionConfig | function | null | Custom animation config object. For more info, see the documentation down on Custom Animation |
\
Basically the same as StackSwitch
except without transitions. However, only the amount of routes will be rendered, this is the same as using the children
props in Route
.
Usage
import React from 'react'
import { View, Text } from 'react-native'
import { NativeRouter } from 'react-router-native'
import { BottomNavigationSwitch } from 'react-router-native-navigation'
export default class App extends React.Component {
render() {
return (
<NativeRouter>
<BottomNavigationSwitch>
<Route exact path="/" render={() => <View><Text>Home</Text></View>} />
<Route path="/settings" render={() => <View><Text>Settings</Text></View>} />
</BottomNavigationSwitch>
<Link to="/"><Text>Home</Text></Link>
<Link to="/settings"><Text>Settings</Text></Link>
</NativeRouter>
);
}
}
Props
Prop | Type | Default | Description |
---|---|---|---|
lazy | boolean | false | Should all routes load at the beginning? |
Note: The above components behaves a bit differently from
react-router
'sSwitch
.StackSwitch
andBottomNavigationSwitch
will render all of the route but only show the matching one. This shouldn't be a problem unless you're relying on it to work that way. If that's not the behaviour you want, simply usingreact-router-native
alone should be sufficient.
Custom Animation
React navigation, a popular library for navigation have their own way of specifying custom animation. This library tries as much as possible to make custom transitions compatible with this library.
There are a few core differences between the react-navigation
history and react-router
history. Because of this, the API for custom transition won't be exactly the same as react-navigation
. However, it might work right off the bat in some scenario.
I personally don't have a need to make this very thorough. If you're willing to make this better, you're more than welcomed to send a PR!
We could pass sufficient data to the parameters and have a separate compatibility layer to map it to react-navigation
(Something like preact-compat)
You could do a simple modification to make libraries such as react-navigation-transitions work. Example:
const compat = config => {
return {
...config,
screenInterpolator: props => {
return config.screenInterpolator({ ...props, scene: { ...props.scene, index: 0 } })
},
}
}
And on your component
...
render() {
return (
<StackSwitch
transitionConfig={() => compat(fromLeft())}
>
...
</StackSwitch>
)
}
...
Differences
Parameters for function aren't the same for the most part. This can be documented better but for now, look at the
StackAnim.js
filetransitionConfig
return value doesn't handle:
headerLeftInterpolator
headerTitleInterpolator
headerRightInterpolator
Header are not handled in this library. Look at current limitation
- The interpolation between screens happens from -1, 0 and 1 instead of between the indexes. Simply imagine
0
to beindex
and you're set. Look at the forked StackViewTransitionConfigs folder to see examples of modified configs to suit this library.
Glueing it yourself (UI customization)
Deep Linking
Simply use <DeepLinking />
provided by react-router-native
Motivation
There are react-navigation
, react-router-navigation
along with countless other libraries out there. Most of them are pretty complicated and tries to do too much. At the end of the day, the API can get pretty confusing and performance doesn't come easily.
Aim
This package should provide a production ready default that can be inserted to any project. Adding to that, developers should be able to create their own glue by using the base component provided by the package.
User should be able to start developing with react-router-native
and effortlessly create great navigation using this package.
Last but not least, it should remain simple but customizable!
Current Limitations
To store previous states of the route, we emulate how Switch
works. This meant that might be differences they behave. Right now, props.match
and other props passed through probably behaves differently than you would expect. We could probably recreate the props ourself and pass it down.
The history API can be a bit limiting for complex navigations. For example, your history stack will get out of control if you don't configure it properly/never reset it. This is not great because all of the entries in the history stack will still be rendered even when it's not used. You can manually reset the stack by mutating the history
object. But this will lead to inconsistency with this library. TODO: Perhaps we should add a method to allow changes from within the Switch components.
No Header support. One of the big decision when this library was made was whether it should support have its own header. In the spirit of keeping things simple, you will have to bring your own header component. There's an example TODO: here that illustrates how to do just that.
However, I'm aware there might be some demand for transitions inside the header itself. I'm open to suggestions on how best to implement it.
There are probably plenty of edge cases that are not be handled yet. Please report them if you find any!
How it works
TODO
- Lifecycle
Roadmap
- Better animation config (Card shadows, etc)
- Web support
- TypeScript
- react-native-reanimated?
Right now we try to follow the API for custom animation with
react-navigation
. There are a bunch of components that we basically recreate in this package because the core history is different fromreact-router
. In the future, it might be worth spending some time to see if we can reuse the components there. Namely:<Transitioner />
, and custom animation. The reason this library still usesAnimated
instead ofreact-native-reanimated
is becausereact-navigation
doesn't support it yet.
Credits
This library won't be possible without all the awesome libraries out there. Credits to react-navigation
, react-router-navigation
, react-native-animated-router
and react-router-transition
for basically doing all the work :). And special thanks to react-native
and react-router
for making all this possible!
6 years ago