0.2.0 • Published 6 years ago

react-router-native-navigation v0.2.0

Weekly downloads
4
License
MIT
Repository
github
Last release
6 years ago

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

PropTypeDefaultDescription
modestringcardThe animation mode. Accepts card or modal.
transitionConfigfunctionnullCustom 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

PropTypeDefaultDescription
lazybooleanfalseShould all routes load at the beginning?

Note: The above components behaves a bit differently from react-router's Switch. StackSwitch and BottomNavigationSwitch 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 using react-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

  1. Parameters for function aren't the same for the most part. This can be documented better but for now, look at the StackAnim.js file

  2. transitionConfig return value doesn't handle:

  • headerLeftInterpolator
  • headerTitleInterpolator
  • headerRightInterpolator

    Header are not handled in this library. Look at current limitation

  1. The interpolation between screens happens from -1, 0 and 1 instead of between the indexes. Simply imagine 0 to be index 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 from react-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 uses Animated instead of react-native-reanimated is because react-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!