Search code examples
react-nativereact-native-router-flux

How to set initial scene in react-native-router-flux with checking the state of the user?


How to set initial scene in react-native-router-flux based upon the user logged in state. Here is my code that I want to achieve this functionality. I want scene 2 if user logged in and scene 1 if user not logged in.

I'm facing an issue with this code it always return a first screen rather than scene 2 I have the user logged in state.

import React, { Component } from 'react';
import { Router, Scene } from 'react-native-router-flux';
import Scene1 from '../Scene1';
import Scene2 from '../Scene2';

// localization strings
import strings from '../config/localization';

import styles from './Styles';

class Routes extends Component {
  state = {
    isUserLogin: false
  }
  async componentDidMount() {
    await AsyncStorage.getItem('user', (err, result) => {
      if (result != null) {
        this.setState({ isUserLogin: JSON.parse(result).isUserLoggedIn });
      }
      if (__DEV__) {
        console.log('routes', this.state); // return trur or false if user logged in or not
      }
    });
  }
  render() {
    return {
      <Router
        backAndroidHandler={() => Actions.pop()}
        sceneStyle={styles.sceneStyle}
        >
          <Scene key="root">
            <Scene
              key="merchants"
              component={Scene1}
              title={strings.selectBusiness}
              navigationBarStyle={styles.navigationBarStyle}
              navBarButtonColor={styles.navBarButtonColor}
              titleStyle={styles.titleStyle}
              initial={!this.state.isUserLogin}
            />
            <Scene
              key="initializeStore"
              component={Scene2}
              hideNavBar
              initial={this.state.isUserLogin}
            />
            <Scene
              key="login"
              component={Login}
              navigationBarStyle={styles.navigationBarStyle}
              navBarButtonColor={styles.navBarButtonColor}
              titleStyle={styles.titleStyle}
              back
              renderBackButton={renderBackButton}
            />
          </Scene>
      </Router>
    }
  }
}

export default Routes;

Solution

  • This can be accomplished with the use of the on, success, and failure props provided to each Scene via RNRF V4

    Below is how you can add to your code:

    import React, { Component } from 'react';
    import { Router, Scene } from 'react-native-router-flux';
    import Scene1 from '../Scene1';
    import Scene2 from '../Scene2';
    
    // localization strings
    import strings from '../config/localization';
    
    import styles from './Styles';
    
    class Routes extends Component {
      state = {
        isUserLogin: false
      }
      async componentDidMount() {
        await AsyncStorage.getItem('user', (err, result) => {
          if (result != null) {
            this.setState({ isUserLogin: JSON.parse(result).isUserLoggedIn });
          }
          if (__DEV__) {
            console.log('routes', this.state); // return trur or false if user logged in or not
          }
        });
      }
    
    // HELPER FUNCTION FOR AUTH
      authenticate = () => {
        this.state.isUserLogin ? true : false
      }
    
      render() {
        return {
          <Router
            backAndroidHandler={() => Actions.pop()}
            sceneStyle={styles.sceneStyle}
            >
              <Scene key="root">
                <Scene 
                  key="Launch" 
                  component="Launch"
                  initial
                  on={this.authenticate}
                  success="Scene2"
                  failure="Scene1"
                />
                <Scene
                  key="merchants"
                  component={Scene1}
                  title={strings.selectBusiness}
                  navigationBarStyle={styles.navigationBarStyle}
                  navBarButtonColor={styles.navBarButtonColor}
                  titleStyle={styles.titleStyle}
                  initial={!this.state.isUserLogin}
                />
                <Scene
                  key="initializeStore"
                  component={Scene2}
                  hideNavBar
                  initial={this.state.isUserLogin}
                />
                <Scene
                  key="login"
                  component={Login}
                  navigationBarStyle={styles.navigationBarStyle}
                  navBarButtonColor={styles.navBarButtonColor}
                  titleStyle={styles.titleStyle}
                  back
                  renderBackButton={renderBackButton}
                />
              </Scene>
          </Router>
        }
      }
    }
    
    export default Routes;
    

    The added Launch scene is just a placeholder scene that appears while RNRF does its logic. You can make this scene simple and just add your logo or whatever you'd like as it will not be appearing for long.

    Food for thought

    Your Router will have a hard time getting to Login this way. Wrapping each section, "logged in scenes" & "logged out scenes", in a stack or scene will allow the on redirects to flow better.

    If you'd like to see how I handle this, check out my repo here!