react-native-router-flux

repository·master·Indexed 27 days ago

https://github.com/aksonov/react-native-router-flux

A React Native Router using Flux architecture that provides a centralized API for managing navigation. It acts as a wrapper over react-navigation to simplify route definitions and inter-screen communication using components like Router, Scene, Stack, Tabs, Drawer, Modal, and Lightbox, alongside an Actions API for navigation tasks.

Tokens
15.1K
Snippets
32
Records
84
Agent score
89%

What's inside react-native-router-flux

  1. Use Sub-scenes for state management

    master

    You can create 'sub-scene' actions by nesting Scene elements as children of a 'base' scene that does not have a component prop. Calling the action for a child scene will update the base scene's state. This is a lightweight alternative to Redux for managing UI states like 'edit mode'.

    <Scene key="myAccount" component={MyAccount} title="My Account">
        <Scene key="viewAccount" />
        <Scene key="editAccount" editMode rightTitle="Save" onRight={()=>Actions.saveAccount()} leftTitle="Cancel" onLeft={()=>Actions.viewAccount()} />
        <Scene key="saveAccount" save />
    </Scene>
  2. Install react-native-router-flux

    master

    To use react-native-router-flux, you must first install its required native dependencies, then add the package itself to your project.

    # 1. Install native dependencies
    npm install react-native-screens || yarn add react-native-screens
    npm install react-native-gesture-handler || yarn add react-native-gesture-handler
    npm install react-native-reanimated || yarn add react-native-reanimated
    npm install react-native-safe-area-context || yarn add react-native-safe-area-context
    npm install @react-native-community/masked-view || yarn add @react-native-community/masked-view
    
    # 2. Install react-native-router-flux
    yarn add react-native-router-flux
  3. Navigate between different nested route hierarchies

    master

    To navigate from a deeply nested route to a route located in a completely different parent hierarchy, you must call the navigation actions for every parent in the target path sequentially.

    For example, if you are at SubRoute3Screen and want to reach SubRoute7Screen which is nested under route2 -> subRoute5 -> subRoute7, you must call:

    import { Actions as NavigationActions } from 'react-native-router-flux'
    
    // ... inside your component
    NavigationActions.route2();
    NavigationActions.subRoute5();
    NavigationActions.subRoute7();
  4. Prevent Router re-renders in Redux

    master

    When using Redux, the Router may re-render whenever the Redux state updates if it is connected and listening to props. To ensure the Router renders only once and maintains performance, follow these architectural patterns:

    1. Limit Connection: Only connect() the Router if you need the dispatch method in its props. Do not listen to specific state changes in the Router itself.
    2. Pre-create Scenes: Use Actions.create() to define your scene tree outside of the render cycle. This prevents scenes from being re-created on every render.
    3. Delegate Logic: Move application logic and state-listening components into children of the Router rather than the Router itself.
    import { Router, Scene, Actions } from 'react-native-router-flux';
    import { connect } from 'react-redux';
    
    // 1. Pre-create scenes via Actions.create()
    const scenes = Actions.create(
        <Scene key="root">
            <Scene key="login" component={myLoginComponent} />
            <Scene key="main" component={myMainComponent} />
        </Scene>
    );
    
    // 2. Connect Router ONLY to get dispatch (don't listen to props)
    const myConnectedRouter = connect()(Router);
    
    export default class MyExportedRouter extends React.Component {
        render() {
            return (
                <Provider store={store}>
                    <myConnectedRouter scenes={scenes} />
                </Provider>
            );
        }
    }
  5. Present Modals from the Root Navigator in Nested Routers

    master

    If you are using nested routers (e.g., a tab bar where each tab has its own Router), modal screens must be defined in the root router to ensure they cover the entire UI (including the tab bar). To achieve this, define the modal route in the root router and set the wrapRouter={true} property on the <Route>.

    <Router>
      <Schema name="modal" sceneConfig={Navigator.SceneConfigs.FloatFromBottom}/>
      <Route name="myModal" component={myModal} title="Modal" schema="modal" wrapRouter={true} />
      <Route name="tabbar">
        <Router footer={TabBar}>
          <Route name="tab1" schema="tab" title="Tab 1" component={Tab1}/>
        </Router>
      </Route>
    </Router>
  6. Migrate from version 2.x to 3.x/4.x

    master

    When migrating from version 2.x to newer versions (3.x/4.x), apply the following breaking changes:

    • Environment: React Native 0.26 or higher is required.
    • Root Container: Use Router as the single root container; do not nest it. For nested scenes, use the Scene element.
    • Scene Definition: Define all scenes at the top-level rather than inside the Router component.
    • Scene Naming: The Route component has been replaced by Scene. The name attribute is replaced by a required key attribute for each scene.
    • Custom Renderers: Instead of using 'custom' types (like modal), use custom scene renderers. Modal scenes are pushed normally, but the custom renderer handles the popup display. To close these popups, use the standard pop action instead of dismiss.
    • Navigation Handlers: onPush, onPop, and similar handlers are no longer supported. Instead, the container re-renders when the navigation state changes; monitor the navigationState property.
    • UI Components: Schema elements, ActionSheet support, navigator.sceneConfig, and header/footer properties on Scene are no longer supported. Include headers and footers directly within your Scene component.
  7. Migrate from version 3.x to 4.x

    master

    When upgrading from version 3.x to 4.x, several breaking changes and architectural shifts occur due to underlying changes in React Navigation. Key changes include:

    • Scene Containers: Scene containers that contain Scene children no longer support the component prop. You must use custom navigators via the navigator prop. Note that scenes cannot have both component and children props simultaneously.
    • Gestures and Duration: duration and panHandlers props are no longer supported. To implement custom behavior, pass a custom navigator via the navigator prop. To disable gestures, use panHandlers={null} or gesturedEnabled={false}.
    • Switch Navigator: The Switch component has been removed. Use onEnter and onExit handlers to implement similar logic.
    • Drawer Syntax: The Drawer implementation has changed. Use the boolean drawer attribute, provide a side menu component via contentComponent, and use Actions.drawerOpen or Actions.drawerClose to control the drawer.
    • Modals: The modal attribute is replaced by the lightbox attribute on the parent Scene (useful for popups like Errors). If standard modal animations are not working, define a separate Scene container with the modal attribute to hold all modals.
    • Transitions: The direction attribute is no longer supported for custom transitions. For vertical transitions, add the modal attribute to the parent Scene.
    • Tab Bar Styling: tabBarSelectedItemStyle is no longer supported. Use React Navigation TabBar parameters such as activeTintColor and inactiveTintColor instead.
    • Navigation Actions: To perform multiple pops at once, use Actions.popTo(sceneName), where sceneName is the name of a specific scene (a scene with a component), not a container.
    • Exports: DefaultRenderer is no longer exported.
  8. Configure Universal and Deep Linking

    master

    You can map URI paths to specific scenes in your Router using the path prop on <Scene> and the uriPrefix prop on <Router>. This allows you to handle deep links by calling the corresponding Actions method with parameters extracted from the URL.

    Example Configuration:

    <Router uriPrefix={'thesocialnetwork.com'}>
      <Scene key="root">
         <Scene key="home" component={Home} />
         <Scene key="profile" path="/profile/:id/" component={Profile} />
         <Scene key="profileForm" path="/edit/profile/:id/" component={ProfileForm} />
      </Scene>
    </Router>

    If a user opens http://thesocialnetwork.com/profile/1234/, you can navigate to that state programmatically using: Actions.profile({ id: 1234 })

  9. Configure Sidebar/Drawer support

    master

    To implement a sidebar or drawer, you must create a custom drawer component that passes router props to its children using React.cloneElement. Then, nest a new <Router> inside your drawer component within your main router configuration.

    1. Create the Drawer Component Ensure the drawer component clones its children and injects the route prop:

    <DrawerLayout>
       {React.Children.map(children, c => React.cloneElement(c, {route: this.props.route}))}
    </DrawerLayout>

    2. Configure the Router Nest the drawer and its internal routes within a parent <Route>:

    <Router>
      <Route name="without-drawer"/>
      <Route name="main">
       <Drawer>
          <Router>
            <Route name="with-drawer-a"/>
            <Route name="with-drawer-b"/>
          </Router>
        </Drawer>
      </Route>
    </Router>
  10. Implement Modals

    master

    To implement modals, use <Modal> as the root component in your <Router>. The first <Scene> nested within <Modal> will render as a normal scene (the root), while subsequent scenes pushed to the stack will render as popups (typically pulling up from the bottom).

    Note: Currently, <Modal> does not support transparent backgrounds.

    <Router>
      <Modal>
        <Scene key="root">
          <Scene key="screen1" initial={true} component={Screen1} />
          <Scene key="screen2" component={Screen2} />
        </Scene>
        <Scene key="statusModal" component={StatusModal} />
        <Scene key="errorModal" component={ErrorModal} />
        <Scene key="loginModal" component={LoginModal} />
      </Modal>
    </Router>
  11. Define routes using the Router and Scene components

    master

    In react-native-router-flux v4, you define your application's routing structure by nesting Scene components inside a Router component. Each Scene requires a unique key and a component prop. You can also provide a title for the scene.

    class App extends React.Component {
      render() {
        return (
          <Router>
            <Scene key="root">
              <Scene key="login" component={Login} title="Login"/>
              <Scene key="register" component={Register} title="Register"/>
              <Scene key="home" component={Home}/>
            </Scene>
          </Router>
        );
      }
    }